codegen.c: fix crash in parallel assignment optimization

The direct literal generation optimization for parallel assignment was
using the RHS count as the loop bound but only filling registers for
LHS variables. When RHS has more elements than LHS (e.g., `a,=1,2`),
this caused uninitialized register indices to be used, generating
garbage opcodes that crashed the VM.

Fix by counting LHS variables and only applying the optimization when
LHS and RHS counts match exactly.

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2025-12-29 18:19:58 +09:00
parent 225cdaa16a
commit f6f8124406
+14 -5
View File
@@ -5170,22 +5170,31 @@ codegen_masgn(codegen_scope *s, node *varnode, node *rhs, int sp, int val)
int regs[16]; /* support up to 16 variables */
node *lhs = masgn_n->pre;
node *rhs_elem = t;
int count = 0;
int rhs_count = 0, lhs_count = 0;
mrb_bool all_simple = TRUE;
/* Count lhs variables */
while (lhs && lhs_count < 16) {
lhs_count++;
lhs = lhs->cdr;
}
/* Count and check rhs are all simple literals */
while (rhs_elem && count < 16) {
while (rhs_elem && rhs_count < 16) {
if (!is_simple_literal(rhs_elem->car)) {
all_simple = FALSE;
break;
}
count++;
rhs_count++;
rhs_elem = rhs_elem->cdr;
}
if (all_simple && count > 0 && all_lvar_pre(s, lhs, regs, count)) {
/* Only apply when lhs and rhs counts match exactly */
lhs = masgn_n->pre;
if (all_simple && lhs_count > 0 && lhs_count == rhs_count &&
all_lvar_pre(s, lhs, regs, lhs_count)) {
/* Direct generation: generate literals into target registers */
rhs_elem = t;
for (int i = 0; i < count; i++) {
for (int i = 0; i < lhs_count; i++) {
gen_literal_to_reg(s, rhs_elem->car, regs[i]);
rhs_elem = rhs_elem->cdr;
}