From 309c55d755f03a842aa22423eb4928fb4f67d188 Mon Sep 17 00:00:00 2001 From: ndossche Date: Tue, 24 Feb 2026 23:12:19 +0100 Subject: [PATCH] Fix memory leak if ossl_bn_new() fails When that call fails, the `bn` BIGNUM is never freed in asn1integer_to_num(). To solve this, use rb_protect(). Example Valgrind report: ``` 32 (24 direct, 8 indirect) bytes in 1 blocks are definitely lost in loss record 11,113 of 25,910 malloc (at /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) CRYPTO_zalloc (at /usr/lib/x86_64-linux-gnu/libcrypto.so.3) BN_new (at /usr/lib/x86_64-linux-gnu/libcrypto.so.3) BN_bin2bn (at /usr/lib/x86_64-linux-gnu/libcrypto.so.3) *asn1integer_to_num (ossl_asn1.c:136) *asn1integer_to_num_i (ossl_asn1.c:165) rb_protect (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3) *decode_int (ossl_asn1.c:356) *int_ossl_asn1_decode0_prim (ossl_asn1.c:777) *ossl_asn1_decode0 (ossl_asn1.c:936) *ossl_asn1_decode_all (ossl_asn1.c:1058) rb_vm_exec (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3) rb_catch_obj (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3) rb_vm_exec (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3) rb_yield (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3) rb_ary_each (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3) rb_vm_exec (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3) rb_yield (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3) rb_ary_each (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3) rb_vm_exec (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3) rb_yield (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3) rb_ary_each (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3) rb_vm_exec (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3) rb_catch_obj (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3) rb_vm_exec (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3) rb_vm_invoke_proc (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3) rb_proc_call_kw (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3) ``` --- ext/openssl/ossl_asn1.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c index 71a87f046..18fa8edeb 100644 --- a/ext/openssl/ossl_asn1.c +++ b/ext/openssl/ossl_asn1.c @@ -130,15 +130,17 @@ asn1integer_to_num(const ASN1_INTEGER *ai) if (!ai) { ossl_raise(rb_eTypeError, "ASN1_INTEGER is NULL!"); } + + num = ossl_bn_new(BN_value_one()); + bn = GetBNPtr(num); + if (ASN1_STRING_type(ai) == V_ASN1_ENUMERATED) - bn = ASN1_ENUMERATED_to_BN(ai, NULL); + bn = ASN1_ENUMERATED_to_BN(ai, bn); else - bn = ASN1_INTEGER_to_BN(ai, NULL); + bn = ASN1_INTEGER_to_BN(ai, bn); if (!bn) ossl_raise(eOSSLError, NULL); - num = ossl_bn_new(bn); - BN_free(bn); return num; }