folly does not build against OpenSSL 4.0 (opaque ASN1_STRING, const X509 accessors); fizz and wangle affected too
Summary
folly does not compile against OpenSSL 4.0 (released 2026-04-14). Two kinds of change bite: ASN1_STRING is now opaque, and a set of X509_* accessors now return const pointers. folly fails in two files; fizz and wangle use the same accessors and will need the same treatment. The fixes are mechanical and the corrected forms are valid on OpenSSL 1.1 and 3.x too, so no version conditionals should be needed.
Filed from packaging cachelib for Fedora: Fedora 45 and Rawhide ship OpenSSL 4.0.2, so the whole folly stack is currently unbuildable there. RHEL 9/10 and Fedora 44 are still on 3.5.
Build failure
folly at 594a1f3161c64f67e8653ce6df46641b16fb38bb (the revision the cachelib snapshot pins), GCC 16, OpenSSL 4.0.2, Fedora Rawhide aarch64:
folly/io/async/ssl/OpenSSLUtils.cpp:126:62: error: invalid use of incomplete type ‘ASN1_OCTET_STRING’ {aka ‘struct asn1_string_st’}
folly/io/async/ssl/OpenSSLUtils.cpp:127:53: error: invalid use of incomplete type ‘ASN1_OCTET_STRING’ {aka ‘struct asn1_string_st’}
folly/io/async/ssl/OpenSSLUtils.cpp:288:45: error: invalid conversion from ‘const X509_NAME*’ {aka ‘const X509_name_st*’} to ‘X509_NAME*’ {aka ‘X509_name_st*’} [-fpermissive]
folly/ssl/OpenSSLCertUtils.cpp:113:34: error: invalid conversion from ‘const asn1_string_st*’ to ‘ASN1_STRING*’ {aka ‘asn1_string_st*’} [-fpermissive]
folly/ssl/OpenSSLCertUtils.cpp:148:42: error: invalid conversion from ‘const X509_NAME*’ {aka ‘const X509_name_st*’} to ‘X509_NAME*’ {aka ‘X509_name_st*’} [-fpermissive]
folly/ssl/OpenSSLCertUtils.cpp:152:41: error: invalid conversion from ‘const X509_NAME*’ {aka ‘const X509_name_st*’} to ‘X509_NAME*’ {aka ‘X509_name_st*’} [-fpermissive]
folly/ssl/OpenSSLCertUtils.cpp:279:45: error: invalid conversion from ‘const X509_EXTENSION*’ {aka ‘const X509_extension_st*’} to ‘X509_EXTENSION*’ {aka ‘X509_extension_st*’} [-fpermissive]
folly/ssl/OpenSSLCertUtils.cpp:292:45: error: invalid conversion from ‘const X509_EXTENSION*’ {aka ‘const X509_extension_st*’} to ‘X509_EXTENSION*’ {aka ‘X509_extension_st*’} [-fpermissive]
folly/ssl/OpenSSLCertUtils.cpp:95:50: error: invalid conversion from ‘const ASN1_OBJECT*’ {aka ‘const asn1_object_st*’} to ‘ASN1_OBJECT*’ {aka ‘asn1_object_st*’} [-fpermissive]What changed in OpenSSL 4.0
From the OpenSSL CHANGES for 4.0.0: "ASN1_STRING has been made opaque. Access to values from ASN1_STRING and related types should be done with the appropriate accessor functions." and "* const-corrected various function return values, particularly in X509 and related areas, and when functions were returning non-const objects owned by a const parameter. Bob Beck * Many functions accepting X509 * arguments, or returning values from a const X509 * have been changed to take/return const "
Prototypes, 3.5 vs 4.0 (include/openssl/x509.h.in):
| function | 3.5 returns | 4.0 returns |
|---|---|---|
X509_get_subject_name |
X509_NAME * |
const X509_NAME * |
X509_get_issuer_name |
X509_NAME * |
const X509_NAME * |
X509_get_ext |
X509_EXTENSION * |
const X509_EXTENSION * |
X509_NAME_get_entry |
X509_NAME_ENTRY * |
const X509_NAME_ENTRY * |
X509_NAME_ENTRY_get_object |
ASN1_OBJECT * |
const ASN1_OBJECT * |
X509_NAME_ENTRY_get_data |
ASN1_STRING * |
const ASN1_STRING * |
X509_EXTENSION_get_object |
ASN1_OBJECT * |
const ASN1_OBJECT * |
X509_EXTENSION_get_data |
ASN1_OCTET_STRING * |
const ASN1_OCTET_STRING * |
X509_get0_notBefore / X509_get0_notAfter |
const ASN1_TIME * |
unchanged |
X509_get_X509_PUBKEY |
X509_PUBKEY * |
const X509_PUBKEY * |
X509_get_serialNumber |
ASN1_INTEGER * |
unchanged |
Plus the opaque ASN1_STRING: ->data / ->length on any ASN1_STRING-derived value (ASN1_OCTET_STRING, ASN1_IA5STRING, the GENERAL_NAME union members such as d.iPAddress and d.dNSName) must become ASN1_STRING_get0_data() / ASN1_STRING_length(), both available since 1.1.0.
Where the stack uses these
Call sites found by grepping the folly, fizz and wangle trees the cachelib snapshot pins (test files included, since they build with -Werror when tests are on):
| function | files |
|---|---|
X509_get_subject_name |
folly io/async/ssl/OpenSSLUtils.cpp, ssl/OpenSSLCertUtils.cpp, io/async/ssl/test/OpenSSLUtilsTest.cpp; fizz protocol/OpenSSLCertificateVerifier.cpp, protocol/CertUtil.h; wangle ssl/SSLUtil.cpp |
X509_get_issuer_name, X509_get_ext, X509_EXTENSION_get_data, X509_EXTENSION_get_object |
folly ssl/OpenSSLCertUtils.cpp |
X509_NAME_get_entry, X509_NAME_ENTRY_get_data |
folly ssl/OpenSSLCertUtils.cpp, io/async/test/SSLContextTest.cpp; wangle ssl/test/SSLContextManagerTest.cpp |
X509_get_serialNumber |
fizz protocol/CertUtil.h |
X509_get0_notBefore / notAfter |
folly ssl/OpenSSLCertUtils.cpp; fizz extensions/delegatedcred/DelegatedCredentialUtils.cpp and its test |
direct ->data / ->length on GENERAL_NAME.d.iPAddress |
folly io/async/ssl/OpenSSLUtils.cpp:126-127 |
sk_GENERAL_NAME_value results treated as mutable |
folly io/async/ssl/OpenSSLUtils.cpp, ssl/OpenSSLCertUtils.cpp; wangle ssl/SSLUtil.cpp |
mvfst and fbthrift have no direct uses. Only the folly failures are confirmed by a compiler; fizz and wangle were not reached, and there may be further sites this grep misses (anything else assigning an X509_* getter result to a non-const pointer, or poking into an ASN1_STRING).
Suggested fix
Take the results as const on the receiving side and use the ASN1_STRING_get0_data() / ASN1_STRING_length() accessors, which compile unchanged against 1.1, 3.x and 4.0. folly/portability/OpenSSL.h currently only models FOLLY_OPENSSL_IS_3X; a 4.x notion may be useful if anything genuinely needs to differ.
Generated with Claude Code
Source: facebook/folly