
Prova de conceito autónoma para CVE-2026-86547, uma desreferenciação de ponteiro NULL em mrubyc op_enter() até à versão 4.0.0.
OP_ENTER do mrubycProva de conceito autônoma para CVE-2026-86547, uma desreferência de ponteiro NULL no manipulador op_enter() do mrubyc até a versão 4.0.0.
mrubyc é uma implementação leve de Ruby para sistemas embarcados. Sua VM de bytecode mantém o ponteiro do quadro de chamada atual em mrbc_vm.callinfo_tail. No nível superior, mrbc_vm_begin() inicializa esse ponteiro como NULL porque ainda não existe um quadro de chamada de método.
Na implementação vulnerável de op_enter() em release4.0.0, o manipulador lê callinfo->reg_offset sem antes verificar se vm->callinfo_tail é NULL:
mrbc_callinfo *callinfo = vm->callinfo_tail;
int reg_offset = callinfo->reg_offset;
Um programa de bytecode .mrb criado maliciosamente pode posicionar OP_ENTER no nível superior, fazendo com que o interpretador alcance esse código com um callinfo_tail NULL e trave por meio de uma desreferência de ponteiro NULL.
CVE: CVE-2026-86547
Tipo: CWE-476 — Desreferência de Ponteiro NULL
Impacto: Disponibilidade / negação de serviço
Afetado: mrubyc até 4.0.0
Severidade: Média, CVSS 6.9 (conforme o aviso)
A PoC espelha os layouts relevantes de mrbc_callinfo e mrbc_vm e reproduz o acesso de memória vulnerável de forma independente do runtime completo do mrubyc.
Ela demonstra dois caminhos:
callinfo_tail é NULL e callinfo->reg_offset é desreferenciado sem uma verificação, produzindo uma falha de segmentação.OP_ENTER de nível superior, seguida por um teste de controle mostrando que um quadro de chamada válido ainda funciona.O harness usa volatile no ponteiro vulnerável e __builtin_trap() em sua descrição para tornar o reprodutor adequado à observação baseada em sanitizer. O acesso vulnerável real é a leitura de callinfo->reg_offset.
gcc -O0 -g -o poc poc.c
./poc
O resultado esperado no caminho vulnerável é uma falha de segmentação após:
[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
O sanitizer deve reportar um SEGV em um endereço correspondente ao campo reg_offset a partir de uma base mrbc_callinfo NULL. Com o layout de estrutura usado aqui, offsetof(mrbc_callinfo, reg_offset) é 0x14.
./poc fixed
A saída esperada inclui:
[FIXED PATH] op_enter with NULL guard
[GUARD] top-level OP_ENTER — rejected safely
[control, valid frame] reg_offset = 5
Fixed path: no crash.
O manipulador vulnerável original está em src/vm.c no mrubyc release4.0.0, por volta da linha 1537. A operação relevante é a desreferência direta de callinfo->reg_offset após atribuir vm->callinfo_tail a callinfo sem uma verificação de NULL.
O código-fonte pós-correção referenciado na pesquisa é o commit 4261cf5e5ae5579e3110dab98a04b91c7d919429.
O harness autônomo demonstra o erro de memória subjacente. No próprio mrubyc, o gatilho exige um arquivo de bytecode .mrb criado maliciosamente contendo uma instrução OP_ENTER no nível superior, fora de uma definição de método. Se uma aplicação carrega e executa arquivos .mrb não confiáveis, um arquivo de bytecode controlado pelo atacante pode, portanto, travar o processo do interpretador.
Esta é uma condição de negação de serviço. A pesquisa não reivindica execução de código, divulgação de informações ou corrupção de memória além da desreferência de NULL.
src/vm.csrc/vm.cOP_SUPER que motivou a auditoria de op_enter()A história da descoberta está documentada em: I Read Someone Else's Bug Report, Then Found The Same Missing Check In The Next Function Over.
A observação-chave da pesquisa foi que op_super() tinha uma verificação de NULL ausente em torno da mesma invariante vm->callinfo_tail. A verificação do manipulador vizinho op_enter() mostrou que a mesma suposição estava presente ali sem a verificação correspondente.