
CVE-2026-86547(mrubyc 4.0.0までのop_enter()におけるNULLポインタ参照)のスタンドアロンな概念実証。
OP_ENTER NULL ポインタ参照外しCVE-2026-86547 のスタンドアロン概念実証です。これは mrubyc の op_enter() ハンドラにおける NULL ポインタ参照外しであり、リリース 4.0.0 まで影響します。
mrubyc は組み込みシステム向けの軽量な Ruby 実装です。そのバイトコード VM は、現在のコールフレームポインタを mrbc_vm.callinfo_tail に保持します。トップレベルでは、まだメソッド呼び出しフレームが存在しないため、mrbc_vm_begin() はこのポインタを NULL に初期化します。
release4.0.0 の脆弱な op_enter() 実装では、ハンドラは vm->callinfo_tail が NULL かどうかを最初に確認せずに callinfo->reg_offset を読み取ります:
mrbc_callinfo *callinfo = vm->callinfo_tail;
int reg_offset = callinfo->reg_offset;
細工された .mrb バイトコードプログラムは OP_ENTER をトップレベルに配置でき、インタプリタが NULL の callinfo_tail でこのコードに到達し、NULL ポインタ参照外しによってクラッシュします。
CVE: CVE-2026-86547
種類: CWE-476 — NULL ポインタ参照外し
影響: 可用性 / サービス拒否
影響を受けるバージョン: mrubyc 4.0.0 まで
深刻度: 中、CVSS 6.9 (アドバイザリによる)
この PoC は、関連する mrbc_callinfo と mrbc_vm のレイアウトを模倣し、完全な mrubyc ランタイムとは独立して脆弱なメモリアクセスを再現します。
これは 2 つのパスを示します:
callinfo_tail が NULL であり、callinfo->reg_offset がガードなしで参照外しされ、セグメンテーションフォルトを引き起こします。OP_ENTER を安全に拒否し、続いて有効なコールフレームが依然として機能することを示す制御テストが行われます。ハーネスは、脆弱なポインタに volatile を使用し、その説明で __builtin_trap() を使用して、再現プログラムをサニタイザベースの観察に適したものにしています。実際の脆弱なアクセスは callinfo->reg_offset の読み取りです。
gcc -O0 -g -o poc poc.c
./poc
脆弱なパスでの期待される結果は、次の出力の後のセグメンテーションフォルトです:
[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
サニタイザは、NULL の mrbc_callinfo ベースからの reg_offset フィールドに対応するアドレスで SEGV を報告するはずです。ここで使用されている構造体レイアウトでは、offsetof(mrbc_callinfo, reg_offset) は 0x14 です。
./poc fixed
期待される出力には次が含まれます:
[FIXED PATH] op_enter with NULL guard
[GUARD] top-level OP_ENTER — rejected safely
[control, valid frame] reg_offset = 5
Fixed path: no crash.
元の脆弱なハンドラは、mrubyc release4.0.0 の src/vm.c の 1537 行目付近にあります。関連する操作は、NULL チェックなしで vm->callinfo_tail を callinfo に代入した後の callinfo->reg_offset の直接参照外しです。
研究で参照されている修正後のソースは、コミット 4261cf5e5ae5579e3110dab98a04b91c7d919429 です。
スタンドアロンハーネスは、根本的なメモリエラーを示しています。mrubyc 自体では、トリガーにはメソッド定義の外側のトップレベルに OP_ENTER 命令を含む細工された .mrb バイトコードファイルが必要です。アプリケーションが信頼できない .mrb ファイルをロードして実行する場合、攻撃者が制御するバイトコードファイルがインタプリタプロセスをクラッシュさせる可能性があります。
これはサービス拒否状態です。この研究は、NULL 参照外しを超えたコード実行、情報漏洩、またはメモリ破壊を主張していません。
src/vm.csrc/vm.cop_enter() の監査のきっかけとなった関連する OP_SUPER NULL チェック問題発見の経緯は次に記録されています: I Read Someone Else's Bug Report, Then Found The Same Missing Check In The Next Function Over。
重要な研究上の観察は、op_super() が同じ vm->callinfo_tail 不変条件の周りに NULL ガードを欠いていたことでした。隣接する op_enter() ハンドラを確認すると、同じ仮定が対応するガードなしでそこに存在していました。