From 2bd18e52dc58bb8ea9679362b9beb3f9ed2d888a Mon Sep 17 00:00:00 2001 From: ndossche Date: Thu, 19 Feb 2026 14:11:30 +0100 Subject: [PATCH 1/2] crypto: fix handling of null BUF_MEM* in ToV8Value() The assignment to `bptr` calls `BIO_get_mem_ptr` which can fail and leave the `bptr` as nullptr. This then later causes a null pointer deref. This is inconsistent with uses of the similar function `BIO_get_mem_data` that do check its return value, e.g. `node::crypto::X509sToArrayOfStrings()`. Solve it by checking for a null pointer and handling the `Nothing` return value at the call sites. --- src/crypto/crypto_keys.cc | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/crypto/crypto_keys.cc b/src/crypto/crypto_keys.cc index e805a984322c83..bf68d600865966 100644 --- a/src/crypto/crypto_keys.cc +++ b/src/crypto/crypto_keys.cc @@ -88,6 +88,7 @@ MaybeLocal ToV8Value( const EVPKeyPointer::AsymmetricKeyEncodingConfig& config) { if (!bio) return {}; BUF_MEM* bptr = bio; + if (!bptr) return {}; if (config.format == EVPKeyPointer::PKFormatType::PEM) { // PEM is an ASCII format, so we will return it as a string. return String::NewFromUtf8( @@ -106,7 +107,12 @@ MaybeLocal WritePrivateKey( const EVPKeyPointer::PrivateKeyEncodingConfig& config) { if (!pkey) return {}; auto res = pkey.writePrivateKey(config); - if (res) return ToV8Value(env, std::move(res.value), config); + if (res) { + auto value = ToV8Value(env, std::move(res.value), config); + if (!value.IsEmpty()) { + return value; + } + } ThrowCryptoError( env, res.openssl_error.value_or(0), "Failed to encode private key"); @@ -119,7 +125,12 @@ MaybeLocal WritePublicKey( const EVPKeyPointer::PublicKeyEncodingConfig& config) { if (!pkey) return {}; auto res = pkey.writePublicKey(config); - if (res) return ToV8Value(env, res.value, config); + if (res) { + auto value = ToV8Value(env, res.value, config); + if (!value.IsEmpty()) { + return value; + } + } ThrowCryptoError( env, res.openssl_error.value_or(0), "Failed to encode public key"); From 5632d1f7dd036870192132fa0224cbda3a814860 Mon Sep 17 00:00:00 2001 From: ndossche Date: Thu, 19 Feb 2026 14:33:04 +0100 Subject: [PATCH 2/2] fixup! Fix in more locations --- src/crypto/crypto_x509.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/crypto/crypto_x509.cc b/src/crypto/crypto_x509.cc index f40f6dd4f2bcaf..6ac4dd2adb38b6 100644 --- a/src/crypto/crypto_x509.cc +++ b/src/crypto/crypto_x509.cc @@ -106,6 +106,8 @@ MaybeLocal ToV8Value(Local context, BIOPointer&& bio) { if (!bio) [[unlikely]] return {}; BUF_MEM* mem = bio; + if (!mem) [[unlikely]] + return {}; Local ret; if (!String::NewFromUtf8(Isolate::GetCurrent(), mem->data, @@ -120,6 +122,8 @@ MaybeLocal ToV8Value(Local context, const BIOPointer& bio) { if (!bio) [[unlikely]] return {}; BUF_MEM* mem = bio; + if (!mem) [[unlikely]] + return {}; Local ret; if (!String::NewFromUtf8(Isolate::GetCurrent(), mem->data, @@ -134,6 +138,8 @@ MaybeLocal ToBuffer(Environment* env, BIOPointer* bio) { if (bio == nullptr || !*bio) [[unlikely]] return {}; BUF_MEM* mem = *bio; + if (!mem) [[unlikely]] + return {}; #ifdef V8_ENABLE_SANDBOX // If the v8 sandbox is enabled, then all array buffers must be allocated // via the isolate. External buffers are not allowed. So, instead of wrapping