Skip to content

Commit 9f0950d

Browse files
matzclaude
andcommitted
codegen.c: fix stack tracking in pattern match branching code
When generating code for pattern matching with potential failures, the success and failure paths both need to pop the matched value. At runtime, only one path executes. But during codegen, both pop() calls affected the compile-time stack pointer (cursp), corrupting register allocation and causing heap-buffer-overflow when accessing symbol tables with wrong indices. Fix by saving/restoring the stack pointer around the branch point, so each path correctly tracks the stack state independently. Co-authored-by: Claude <noreply@anthropic.com>
1 parent da2d652 commit 9f0950d

File tree

1 file changed

+7
-4
lines changed

1 file changed

+7
-4
lines changed

mrbgems/mruby-compiler/core/codegen.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6603,13 +6603,14 @@ codegen(codegen_scope *s, node *tree, int val)
66036603
/* Generate pattern matching code */
66046604
codegen_pattern(s, mp->pattern, head, &fail_pos, known_array_len);
66056605

6606-
/* Pattern matched */
6607-
pop(); /* pop the value */
66086606
pattern_fail_handling:
66096607
if (fail_pos != JMPLINK_START) {
66106608
/* Pattern can fail - generate failure handling code */
66116609
uint32_t match_pos;
6610+
int saved_sp = cursp(); /* save stack pointer before branching */
66126611

6612+
/* Success path: pattern matched */
6613+
pop(); /* pop the value */
66136614
if (val) {
66146615
/* 'in' pattern returns true, '=>' pattern returns nil */
66156616
if (mp->raise_on_fail) {
@@ -6636,7 +6637,8 @@ codegen(codegen_scope *s, node *tree, int val)
66366637
dispatch_linked(s, fail_pos);
66376638
}
66386639

6639-
/* Pattern failed */
6640+
/* Failure path: restore stack pointer (value still on stack at runtime) */
6641+
s->sp = saved_sp;
66406642
pop(); /* pop the value */
66416643
if (mp->raise_on_fail) {
66426644
/* expr => pattern: raise NoMatchingPatternError */
@@ -6667,7 +6669,8 @@ codegen(codegen_scope *s, node *tree, int val)
66676669
dispatch(s, match_pos);
66686670
}
66696671
else {
6670-
/* Pattern always matches - push result if needed */
6672+
/* Pattern always matches - pop value and push result if needed */
6673+
pop(); /* pop the value */
66716674
if (val) {
66726675
if (mp->raise_on_fail) {
66736676
gen_load_nil(s, 1); /* '=>' pattern returns nil */

0 commit comments

Comments
 (0)