Root cause
Injection & unsafe execution introduced
mruby-compiler: optimize JMPNOT+JMP to JMPIF in pattern matching
How AI contributed: Direct introductionPublished Feb 6, 2026 in
sysfce2/mruby
Root cause
mruby-compiler: optimize JMPNOT+JMP to JMPIF in pattern matching
Fix
mruby-compiler: fix bytecode corruption in pattern matching optimization
AI-assisted fix: Claude Code · Yukihiro "Matz" Matsumoto
Case facts
@@ -6402,10 +6402,23 @@ codegen(codegen_scope *s, node *tree, int val) genop_1(s, OP_LOADT, cursp()); push(); }- match_pos = genjmp(s, OP_JMP, JMPLINK_START);++ /* Optimize: single JMPNOT can be inverted to JMPIF, eliminating JMP */+ /* Conditions: (1) single entry in fail_pos chain, and+ * (2) JMPNOT is immediately before current position (no code between) */+ if ((int32_t)(fail_pos + 2) + (int16_t)PEEK_S(s->iseq+fail_pos) == 0 &&+ fail_pos + 2 == s->pc) {+ /* Single failure point - invert JMPNOT to JMPIF */+ s->iseq[fail_pos - 2] = OP_JMPIF;+ match_pos = fail_pos;+ }+ else {+ /* Multiple failure points - need JMP to skip error handling */+ match_pos = genjmp(s, OP_JMP, JMPLINK_START);+ dispatch_linked(s, fail_pos);+ } /* Pattern failed */- dispatch_linked(s, fail_pos); pop(); /* pop the value */ if (mp->raise_on_fail) { /* expr => pattern: raise NoMatchingPatternError */@@ -6626,10 +6626,12 @@ codegen(codegen_scope *s, node *tree, int val) } /* Optimize: single JMPNOT can be inverted to JMPIF, eliminating JMP */- /* Conditions: (1) single entry in fail_pos chain, and- * (2) JMPNOT is immediately before current position (no code between) */+ /* Conditions: (1) single entry in fail_pos chain,+ * (2) JMPNOT is immediately before current position (no code between), and+ * (3) the instruction is actually JMPNOT (not JMP from undefined pinned var) */ if ((int32_t)(fail_pos + 2) + (int16_t)PEEK_S(s->iseq+fail_pos) == 0 &&- fail_pos + 2 == s->pc) {+ fail_pos + 2 == s->pc &&+ s->iseq[fail_pos - 2] == OP_JMPNOT) { /* Single failure point - invert JMPNOT to JMPIF */ s->iseq[fail_pos - 2] = OP_JMPIF; match_pos = fail_pos;AI-assisted change 649ba9b50f386aa9c60cc1c3f4db76b722d4bf971829deb6eebbfc6cac42abdf · Fix ea03002654674f589540573a9c336337103e03ffb85d911aa5ad2e6ea7e6232f