From eea9e30979a9dc603349ca211d434e33992eb0d1 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 5 Feb 2026 07:52:25 +0900 Subject: [PATCH] mruby-compiler: fix heap-buffer-overflow in pattern alternation codegen The JMPNOT-to-JMPIF optimization in NODE_PAT_ALT assumed the fail chain always ends with OP_JMPNOT (format BS), but NODE_PAT_PIN generates OP_JMP (format S) when the pinned variable is undefined. Writing OP_JMPIF at left_fail-2 then corrupts the preceding instruction's operand, causing out-of-bounds pool access at runtime. Co-authored-by: Claude --- mrbgems/mruby-compiler/core/codegen.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index b9f2781b7..63e66136e 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -4498,9 +4498,12 @@ codegen_pattern(codegen_scope *s, node *pattern, int target, uint32_t *fail_pos, * 1. Left pattern is not another NODE_PAT_ALT (avoid recursion issues) * 2. Left pattern generated at least one JMPNOT * 3. The last JMPNOT is immediately before current position + * 4. The instruction is actually OP_JMPNOT (not OP_JMP which has + * different format S vs BS - converting OP_JMP would corrupt bytecode) * In this case, convert JMPNOT to JMPIF and skip generating JMP */ if (node_type(pat_alt->left) != NODE_PAT_ALT && - left_fail != JMPLINK_START && left_fail + 2 == s->pc) { + left_fail != JMPLINK_START && left_fail + 2 == s->pc && + s->iseq[left_fail - 2] == OP_JMPNOT) { /* Extract the previous link from the JMPNOT chain. * The chain uses relative offsets where the end is marked by * an offset that points to address 0 (i.e., (pos+2)+offset == 0) */