Skip to content

Commit 48ccf3e

Browse files
committed
newFOROP: fix crash when optimizing 2-var for over builtin::indexed
OP_ENTERSUB isn't necessarily a LISTOP, apparently, so we can't just grab its op_last. Instead, copy/paste logic from elsewhere in op.c to find the cvop. Also, avoid crashing on "fake" pad entries that represent lexical subs from outer scopes by climbing up the scope chain until we reach a real pad entry. Fixes #23405.
1 parent 22496f1 commit 48ccf3e

File tree

2 files changed

+23
-3
lines changed

2 files changed

+23
-3
lines changed

op.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9671,7 +9671,7 @@ S_op_is_cv_xsub(pTHX_ OP *o, XSUBADDR_t xsub)
96719671
}
96729672

96739673
case OP_PADCV:
9674-
cv = (CV *)PAD_SVl(o->op_targ);
9674+
cv = find_lexical_cv(o->op_targ);
96759675
assert(cv && SvTYPE(cv) == SVt_PVCV);
96769676
break;
96779677

@@ -9689,10 +9689,17 @@ S_op_is_cv_xsub(pTHX_ OP *o, XSUBADDR_t xsub)
96899689
static bool
96909690
S_op_is_call_to_cv_xsub(pTHX_ OP *o, XSUBADDR_t xsub)
96919691
{
9692-
if(o->op_type != OP_ENTERSUB)
9692+
if (o->op_type != OP_ENTERSUB)
96939693
return false;
96949694

9695-
OP *cvop = cLISTOPx(cUNOPo->op_first)->op_last;
9695+
OP *aop = cUNOPo->op_first;
9696+
if (!OpHAS_SIBLING(aop)) {
9697+
aop = cUNOPx(aop)->op_first;
9698+
}
9699+
aop = OpSIBLING(aop);
9700+
OP *cvop;
9701+
for (cvop = aop; OpHAS_SIBLING(cvop); cvop = OpSIBLING(cvop)) ;
9702+
96969703
return op_is_cv_xsub(cvop, xsub);
96979704
}
96989705

t/op/for-many.t

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,4 +498,17 @@ is($continue, 'xx', 'continue reached twice');
498498
is("@have", "Pointy end Up Flamey end Down", 'for my ($one, $two)');
499499
}
500500

501+
# GH #23405 - segfaults when compiling 2-var for loops
502+
{
503+
my $dummy = sub {};
504+
for my ($x, $y) (main->$dummy) {}
505+
pass '2-var for does not crash on method calls';
506+
507+
my sub dummy {}
508+
sub {
509+
for my ($x, $y) (dummy) {}
510+
}->();
511+
pass '2-var for does not crash on lexical sub calls';
512+
}
513+
501514
done_testing();

0 commit comments

Comments
 (0)