Check if destinations are too distant; fix fix
MODIFY
mrbgems/mruby-compiler/core/codegen.c
mrbgems/mruby-compiler/core/codegen.c
@@ -392,6 +392,14 @@ scope_error(codegen_scope *s)
exit(EXIT_FAILURE);
}
+static void
+distcheck(codegen_scope *s, int diff)
+{
+ if (diff > MAXARG_sBx || diff < -MAXARG_sBx) {
+ codegen_error(s, "too distant jump address");
+ }
+}
+
static inline void
dispatch(codegen_scope *s, int pc)
{
@@ -413,9 +421,7 @@ dispatch(codegen_scope *s, int pc)
scope_error(s);
break;
}
- if (diff > MAXARG_sBx) {
- codegen_error(s, "too distant jump address");
- }
+ distcheck(s, diff);
s->iseq[pc] = MKOP_AsBx(c, GETARG_A(i), diff);
}
@@ -1364,6 +1370,7 @@ codegen(codegen_scope *s, node *tree, int val)
pop();
genop(s, MKOP_ABC(OP_RESCUE, exc, cursp(), 1));
}
+ distcheck(s, pos2);
tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
pos2 = tmp;
if (n4) {
@@ -1381,6 +1388,7 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, n3->cdr->cdr->car, val);
if (val) pop();
}
+ distcheck(s, exend);
tmp = genop(s, MKOP_sBx(OP_JMP, exend));
exend = tmp;
n2 = n2->cdr;
@@ -1526,6 +1534,7 @@ codegen(codegen_scope *s, node *tree, int val)
dispatch(s, lp->pc1);
codegen(s, tree->car, VAL);
pop();
+ distcheck(s, lp->pc2 - s->pc);
genop(s, MKOP_AsBx(OP_JMPIF, cursp(), lp->pc2 - s->pc));
loop_pop(s, val);
@@ -1542,6 +1551,7 @@ codegen(codegen_scope *s, node *tree, int val)
dispatch(s, lp->pc1);
codegen(s, tree->car, VAL);
pop();
+ distcheck(s, lp->pc2 - s->pc);
genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), lp->pc2 - s->pc));
loop_pop(s, val);
@@ -1584,6 +1594,7 @@ codegen(codegen_scope *s, node *tree, int val)
else {
pop();
}
+ distcheck(s, pos2);
tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
pos2 = tmp;
n = n->cdr;
@@ -1594,6 +1605,7 @@ codegen(codegen_scope *s, node *tree, int val)
}
codegen(s, tree->car->cdr, val);
if (val) pop();
+ distcheck(s, pos3);
tmp = genop(s, MKOP_sBx(OP_JMP, pos3));
pos3 = tmp;
if (pos1) dispatch(s, pos1);
@@ -2091,6 +2103,7 @@ codegen(codegen_scope *s, node *tree, int val)
genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
}
codegen(s, tree, NOVAL);
+ distcheck(s, s->loop->pc1 - s->pc);
genop(s, MKOP_sBx(OP_JMP, s->loop->pc1 - s->pc));
}
else {
@@ -2114,6 +2127,7 @@ codegen(codegen_scope *s, node *tree, int val)
if (s->ensure_level > s->loop->ensure_level) {
genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
}
+ distcheck(s, s->loop->pc2 - s->pc);
genop(s, MKOP_sBx(OP_JMP, s->loop->pc2 - s->pc));
}
if (val) push();
@@ -2146,6 +2160,7 @@ codegen(codegen_scope *s, node *tree, int val)
if (s->ensure_level > lp->ensure_level) {
genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - lp->ensure_level), NOVAL);
}
+ distcheck(s, s->loop->pc1 - s->pc);
genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc));
}
}
@@ -3005,6 +3020,7 @@ loop_break(codegen_scope *s, node *tree)
if (tree) {
genop_peep(s, MKOP_AB(OP_MOVE, loop->acc, cursp()), NOVAL);
}
+ distcheck(s, s->loop->pc3);
tmp = genop(s, MKOP_sBx(OP_JMP, loop->pc3));
loop->pc3 = tmp;
}

MODIFY
src/codedump.c
src/codedump.c
@@ -189,13 +189,13 @@ codedump(mrb_state *mrb, mrb_irep *irep)
print_lv(mrb, irep, c, RA);
break;
case OP_JMP:
- printf("OP_JMP\t%03d\n", i+GETARG_sBx(c));
+ printf("OP_JMP\t%03d (%d)\n", i+GETARG_sBx(c), GETARG_sBx(c));
break;
case OP_JMPIF:
- printf("OP_JMPIF\tR%d\t%03d\n", GETARG_A(c), i+GETARG_sBx(c));
+ printf("OP_JMPIF\tR%d\t%03d (%d)\n", GETARG_A(c), i+GETARG_sBx(c), GETARG_sBx(c));
break;
case OP_JMPNOT:
- printf("OP_JMPNOT\tR%d\t%03d\n", GETARG_A(c), i+GETARG_sBx(c));
+ printf("OP_JMPNOT\tR%d\t%03d (%d)\n", GETARG_A(c), i+GETARG_sBx(c), GETARG_sBx(c));
break;
case OP_SEND:
printf("OP_SEND\tR%d\t:%s\t%d\n", GETARG_A(c),

Check if destinations are too distant; fix #3900 fix #3901