
Proof of concept autonomo per CVE-2026-86547, un dereferenziamento di puntatore NULL in mrubyc op_enter() fino alla versione 4.0.0.
OP_ENTER di mrubycProof of concept autonomo per CVE-2026-86547, una dereferenziazione di puntatore NULL nel gestore op_enter() di mrubyc fino alla release 4.0.0.
mrubyc è un'implementazione leggera di Ruby per sistemi embedded. La sua VM a bytecode mantiene il puntatore al call-frame corrente in mrbc_vm.callinfo_tail. A livello top, mrbc_vm_begin() inizializza questo puntatore a NULL poiché non esiste ancora alcun frame di chiamata di metodo.
Nell'implementazione vulnerabile di op_enter() in release4.0.0, il gestore legge callinfo->reg_offset senza prima verificare se vm->callinfo_tail è NULL:
mrbc_callinfo *callinfo = vm->callinfo_tail;
int reg_offset = callinfo->reg_offset;
Un programma bytecode .mrb appositamente costruito può posizionare OP_ENTER a livello top, causando l'accesso dell'interprete a questo codice con un callinfo_tail NULL e un crash per dereferenziazione di puntatore NULL.
CVE: CVE-2026-86547
Tipo: CWE-476 — Dereferenziazione di puntatore NULL
Impatto: Disponibilità / denial of service
Affetto: mrubyc fino alla 4.0.0
Gravità: Media, CVSS 6.9 (secondo l'advisory)
Il PoC rispecchia i layout rilevanti di mrbc_callinfo e mrbc_vm e riproduce l'accesso di memoria vulnerabile indipendentemente dal runtime mrubyc completo.
Dimostra due percorsi:
callinfo_tail è NULL e callinfo->reg_offset viene dereferenziato senza una guardia, producendo un segmentation fault.OP_ENTER a livello top, seguito da un test di controllo che mostra che un frame di chiamata valido funziona ancora.L'harness utilizza volatile sul puntatore vulnerabile e __builtin_trap() nella sua descrizione per rendere il reproducer adatto all'osservazione basata su sanitizer. L'accesso vulnerabile effettivo è la lettura di callinfo->reg_offset.
gcc -O0 -g -o poc poc.c
./poc
Il risultato atteso sul percorso vulnerabile è un segmentation fault dopo:
[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
Il sanitizer dovrebbe segnalare un SEGV su un indirizzo corrispondente al campo reg_offset da una base mrbc_callinfo NULL. Con il layout della struttura utilizzato qui, offsetof(mrbc_callinfo, reg_offset) è 0x14.
./poc fixed
L'output atteso include:
[FIXED PATH] op_enter with NULL guard
[GUARD] top-level OP_ENTER — rejected safely
[control, valid frame] reg_offset = 5
Fixed path: no crash.
Il gestore vulnerabile originale si trova in src/vm.c in mrubyc release4.0.0, intorno alla riga 1537. L'operazione rilevante è la dereferenziazione diretta di callinfo->reg_offset dopo aver assegnato vm->callinfo_tail a callinfo senza un controllo NULL.
Il sorgente post-fix a cui si fa riferimento nella ricerca è il commit 4261cf5e5ae5579e3110dab98a04b91c7d919429.
L'harness autonomo dimostra l'errore di memoria sottostante. In mrubyc stesso, il trigger richiede un file bytecode .mrb appositamente costruito contenente un'istruzione OP_ENTER a livello top, al di fuori di una definizione di metodo. Se un'applicazione carica ed esegue file .mrb non attendibili, un file bytecode controllato dall'attaccante può quindi mandare in crash il processo dell'interprete.
Questa è una condizione di denial-of-service. La ricerca non rivendica esecuzione di codice, divulgazione di informazioni o corruzione di memoria oltre la dereferenziazione NULL.
src/vm.csrc/vm.cOP_SUPER che ha motivato l'audit di op_enter()La storia della scoperta è documentata in: I Read Someone Else's Bug Report, Then Found The Same Missing Check In The Next Function Over.
L'osservazione chiave della ricerca è stata che op_super() presentava una guardia NULL mancante attorno alla stessa invariante vm->callinfo_tail. Controllando il gestore adiacente op_enter() è emerso che la stessa assunzione era presente anche lì senza la corrispondente guardia.