Skip to content

Commit b4dcd72

Browse files
author
Father Chrysostomos
committed
[perl #132854] Allow goto into first arg of bin op
This particular case does not risk any stack corruption, and there is a CPAN module depending on it working (PerlX::AsyncAwait).
1 parent d594884 commit b4dcd72

File tree

4 files changed

+28
-3
lines changed

4 files changed

+28
-3
lines changed

pod/perldelta.pod

+6-1
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,12 @@ XXX Changes (i.e. rewording) of diagnostic messages go here
284284

285285
=item *
286286

287-
XXX Describe change here
287+
The new (as of 5.27.8) restriction forbidding use of C<goto> to enter the
288+
argument of a binary or list expression (see L<perldiag/"Can't
289+
E<quot>gotoE<quot> into a binary or list expression">) has been relaxed to
290+
allow entering the I<first> argument of an operator that takes a fixed
291+
number of arguments, since this is a case that will not cause stack
292+
corruption. [perl #132854]
288293

289294
=back
290295

pod/perlfunc.pod

+3-1
Original file line numberDiff line numberDiff line change
@@ -3458,7 +3458,9 @@ deprecated and will issue a warning. Even then, it may not be used to
34583458
go into any construct that requires initialization, such as a
34593459
subroutine, a C<foreach> loop, or a C<given>
34603460
block. In general, it may not be used to jump into the parameter
3461-
of a binary or list operator. It also can't be used to go into a
3461+
of a binary or list operator, but it may be used to jump into the
3462+
I<first> parameter of a binary operator or other operator that takes
3463+
a fixed number of arguments. It also can't be used to go into a
34623464
construct that is optimized away.
34633465

34643466
The C<goto &NAME> form is quite different from the other forms of

pp_ctl.c

+8
Original file line numberDiff line numberDiff line change
@@ -2687,6 +2687,7 @@ S_dofindlabel(pTHX_ OP *o, const char *label, STRLEN len, U32 flags, OP **opstac
26872687
*ops = 0;
26882688
if (o->op_flags & OPf_KIDS) {
26892689
OP *kid;
2690+
OP * const kid1 = cUNOPo->op_first;
26902691
/* First try all the kids at this level, since that's likeliest. */
26912692
for (kid = cUNOPo->op_first; kid; kid = OpSIBLING(kid)) {
26922693
if (kid->op_type == OP_NEXTSTATE || kid->op_type == OP_DBSTATE) {
@@ -2709,6 +2710,7 @@ S_dofindlabel(pTHX_ OP *o, const char *label, STRLEN len, U32 flags, OP **opstac
27092710
}
27102711
}
27112712
for (kid = cUNOPo->op_first; kid; kid = OpSIBLING(kid)) {
2713+
bool first_kid_of_binary = FALSE;
27122714
if (kid == PL_lastgotoprobe)
27132715
continue;
27142716
if (kid->op_type == OP_NEXTSTATE || kid->op_type == OP_DBSTATE) {
@@ -2721,8 +2723,14 @@ S_dofindlabel(pTHX_ OP *o, const char *label, STRLEN len, U32 flags, OP **opstac
27212723
else
27222724
*ops++ = kid;
27232725
}
2726+
if (kid == kid1 && ops != opstack && ops[-1] == UNENTERABLE) {
2727+
first_kid_of_binary = TRUE;
2728+
ops--;
2729+
}
27242730
if ((o = dofindlabel(kid, label, len, flags, ops, oplimit)))
27252731
return o;
2732+
if (first_kid_of_binary)
2733+
*ops++ = UNENTERABLE;
27262734
}
27272735
}
27282736
*ops = 0;

t/op/goto.t

+11-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ BEGIN {
1010

1111
use warnings;
1212
use strict;
13-
plan tests => 122;
13+
plan tests => 123;
1414
our $TODO;
1515

1616
my $deprecated = 0;
@@ -870,3 +870,13 @@ sub _routine {
870870
}
871871
_routine();
872872
pass("bug 132799");
873+
874+
# [perl #132854]
875+
# Goto the *first* parameter of a binary expression, which is harmless.
876+
eval {
877+
goto __GEN_2;
878+
my $sent = do {
879+
__GEN_2:
880+
};
881+
};
882+
is $@,'', 'goto the first parameter of a binary expression [perl #132854]';

0 commit comments

Comments
 (0)