Skip to content

Fix missing error check on BIO_get_mem_ptr()#1013

Merged
rhenium merged 1 commit intoruby:masterfrom
ndossche:clesss-4
Feb 26, 2026
Merged

Fix missing error check on BIO_get_mem_ptr()#1013
rhenium merged 1 commit intoruby:masterfrom
ndossche:clesss-4

Conversation

@ndossche
Copy link
Contributor

LibreSSL docs state this can fail. OpenSSL has no docs for this, but the implementation goes via BIO_ctrl() which can fail (e.g. via a callback). Example Valgrind trace:

Invalid read of size 1
  memmove (at /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
  memcpy (string_fortified.h:29)
  ossl_str_new (ossl.c:107)
  ossl_membio2str (ossl_bio.c:36)
  ossl_x509ext_get_value (ossl_x509ext.c:390)
  <unknown stack frame>
  <unknown stack frame>
  <unknown stack frame>
  rb_vm_exec (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3)
  <unknown stack frame>
  <unknown stack frame>
  rb_catch_obj (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3)
  <unknown stack frame>
  <unknown stack frame>
  <unknown stack frame>
  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)
  <unknown stack frame>
  <unknown stack frame>
  <unknown stack frame>
  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)
  <unknown stack frame>
  <unknown stack frame>
  <unknown stack frame>
  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)
  <unknown stack frame>
  <unknown stack frame>
  <unknown stack frame>
  rb_vm_exec (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3)
  <unknown stack frame>
  <unknown stack frame>
  rb_catch_obj (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3)
  <unknown stack frame>
  <unknown stack frame>
  <unknown stack frame>
  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)
  <unknown stack frame>
  <unknown stack frame>
  <unknown stack frame>
  ruby_run_node (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3)
  <unknown stack frame>
  (below main) (libc_start_call_main.h:58)

This was found by a hybrid static-dynamic analyser that looks for inconsistent handling of error checks in bindings.

LibreSSL docs state this can fail. OpenSSL has no docs for this, but the
implementation goes via BIO_ctrl() which can fail (e.g. via a callback).
Example Valgrind trace:
```
Invalid read of size 1
  memmove (at /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
  memcpy (string_fortified.h:29)
  ossl_str_new (ossl.c:107)
  ossl_membio2str (ossl_bio.c:36)
  ossl_x509ext_get_value (ossl_x509ext.c:390)
  <unknown stack frame>
  <unknown stack frame>
  <unknown stack frame>
  rb_vm_exec (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3)
  <unknown stack frame>
  <unknown stack frame>
  rb_catch_obj (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3)
  <unknown stack frame>
  <unknown stack frame>
  <unknown stack frame>
  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)
  <unknown stack frame>
  <unknown stack frame>
  <unknown stack frame>
  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)
  <unknown stack frame>
  <unknown stack frame>
  <unknown stack frame>
  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)
  <unknown stack frame>
  <unknown stack frame>
  <unknown stack frame>
  rb_vm_exec (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3)
  <unknown stack frame>
  <unknown stack frame>
  rb_catch_obj (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3)
  <unknown stack frame>
  <unknown stack frame>
  <unknown stack frame>
  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)
  <unknown stack frame>
  <unknown stack frame>
  <unknown stack frame>
  ruby_run_node (at /usr/lib/x86_64-linux-gnu/libruby-3.2.so.3.2.3)
  <unknown stack frame>
  (below main) (libc_start_call_main.h:58)
```
Copy link
Member

@rhenium rhenium left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems OpenSSL documented this, too, actually:

BIO_set_mem_eof_return(), BIO_set_mem_buf() and BIO_get_mem_ptr() return 1 on success or a value which is less than or equal to 0 if an error occurred.

I don't expect it to actually fail with an unmodified OpenSSL, as the BIO shouldn't have a callback attached, but the return value should still be checked.

@rhenium rhenium merged commit 785b67a into ruby:master Feb 26, 2026
47 of 48 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants