
Prueba de concepto independiente para CVE-2026-86547, una desreferencia de puntero NULL en mrubyc op_enter() hasta la versión 4.0.0.
OP_ENTER de mrubycPrueba de concepto independiente para CVE-2026-86547, una desreferencia de puntero NULL en el manejador op_enter() de mrubyc hasta la versión 4.0.0.
mrubyc es una implementación ligera de Ruby para sistemas embebidos. Su máquina virtual de bytecode mantiene el puntero del marco de llamada actual en mrbc_vm.callinfo_tail. En el nivel superior, mrbc_vm_begin() inicializa este puntero a NULL porque todavía no existe ningún marco de llamada a método.
En la implementación vulnerable de op_enter() en release4.0.0, el manejador lee callinfo->reg_offset sin comprobar primero si vm->callinfo_tail es NULL:
mrbc_callinfo *callinfo = vm->callinfo_tail;
int reg_offset = callinfo->reg_offset;
Un programa de bytecode .mrb manipulado puede colocar OP_ENTER en el nivel superior, provocando que el intérprete alcance este código con un callinfo_tail NULL y falle mediante una desreferencia de puntero NULL.
CVE: CVE-2026-86547
Tipo: CWE-476 — Desreferencia de puntero NULL
Impacto: Disponibilidad / denegación de servicio
Afectado: mrubyc hasta 4.0.0
Gravedad: Media, CVSS 6.9 (según el aviso)
La PoC replica los diseños relevantes de mrbc_callinfo y mrbc_vm y reproduce el acceso vulnerable a memoria de forma independiente del runtime completo de mrubyc.
Demuestra dos rutas:
callinfo_tail es NULL y se desreferencia callinfo->reg_offset sin una comprobación, produciendo un fallo de segmentación.OP_ENTER de nivel superior, seguida de una prueba de control que muestra que un marco de llamada válido sigue funcionando.El arnés usa volatile en el puntero vulnerable y __builtin_trap() en su descripción para hacer que el reproductor sea adecuado para la observación basada en sanitizers. El acceso vulnerable real es la lectura de callinfo->reg_offset.
gcc -O0 -g -o poc poc.c
./poc
El resultado esperado en la ruta vulnerable es un fallo de segmentación después de:
[VULNERABLE PATH] op_enter without NULL guard
vm->callinfo_tail = NULL (top-level frame)
About to dereference NULL...
gcc -O0 -g -fsanitize=address -fno-omit-frame-pointer -o poc-asan poc.c
./poc-asan
El sanitizer debería informar de un SEGV en una dirección correspondiente al campo reg_offset desde una base mrbc_callinfo NULL. Con el diseño de estructura usado aquí, offsetof(mrbc_callinfo, reg_offset) es 0x14.
./poc fixed
La salida esperada incluye:
[FIXED PATH] op_enter with NULL guard
[GUARD] top-level OP_ENTER — rejected safely
[control, valid frame] reg_offset = 5
Fixed path: no crash.
El manejador vulnerable original está en src/vm.c en mrubyc release4.0.0, alrededor de la línea 1537. La operación relevante es la desreferencia directa de callinfo->reg_offset después de asignar vm->callinfo_tail a callinfo sin una comprobación de NULL.
El código fuente posterior a la corrección referenciado en la investigación es el commit 4261cf5e5ae5579e3110dab98a04b91c7d919429.
El arnés independiente demuestra el error de memoria subyacente. En el propio mrubyc, el desencadenante requiere un archivo de bytecode .mrb manipulado que contenga una instrucción OP_ENTER en el nivel superior, fuera de una definición de método. Si una aplicación carga y ejecuta archivos .mrb no confiables, un archivo de bytecode controlado por un atacante puede, por lo tanto, provocar el fallo del proceso del intérprete.
Esta es una condición de denegación de servicio. La investigación no afirma ejecución de código, revelación de información ni corrupción de memoria más allá de la desreferencia de NULL.
src/vm.csrc/vm.c posterior a la correcciónOP_SUPER que motivó la auditoría de op_enter()La historia del descubrimiento está documentada en: I Read Someone Else's Bug Report, Then Found The Same Missing Check In The Next Function Over.
La observación clave de la investigación fue que op_super() tenía una comprobación de NULL ausente en torno al mismo invariante vm->callinfo_tail. Al revisar el manejador vecino op_enter() se mostró que la misma suposición estaba presente allí sin la comprobación correspondiente.