Skip to content

Commit 40c98c9

Browse files
tonycozmauke
authored andcommitted
class.c, injected_constructor: prevent loop exits exiting
Using last, next etc would pop the context stack to above the call_sv(), generally resulting in a crash or assertion failure. The search the context to pop to stops at the top of the current context stack, and PUSHSTACKi() switches to a new stack, preventing the search from finding any loop outside the call_sv() Similar to #16608
1 parent 7a873fe commit 40c98c9

File tree

4 files changed

+36
-1
lines changed

4 files changed

+36
-1
lines changed

class.c

+5
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ XS(injected_constructor)
175175

176176
SV *self = sv_2mortal(newRV_noinc(instance));
177177

178+
PUSHSTACKi(PERLSI_CONSTRUCTOR);
179+
178180
assert(aux->xhv_class_initfields_cv);
179181
{
180182
ENTER;
@@ -221,6 +223,9 @@ XS(injected_constructor)
221223
}
222224
}
223225

226+
POPSTACK;
227+
SPAGAIN;
228+
224229
if(params && hv_iterinit(params) > 0) {
225230
/* TODO: consider sorting these into a canonical order, but that's awkward */
226231
HE *he = hv_iternext(params);

cop.h

+1
Original file line numberDiff line numberDiff line change
@@ -1259,6 +1259,7 @@ struct context {
12591259
#define PERLSI_MULTICALL 10
12601260
#define PERLSI_REGCOMP 11
12611261
#define PERLSI_SMARTMATCH 12
1262+
#define PERLSI_CONSTRUCTOR 13
12621263

12631264
struct stackinfo {
12641265
AV * si_stack; /* stack for current runlevel */

deb.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,8 @@ static const char * const si_names[] = {
238238
"REQUIRE",
239239
"MULTICALL",
240240
"REGCOMP",
241-
"SMARTMATCH"
241+
"SMARTMATCH",
242+
"CONSTRUCTOR"
242243
};
243244
#endif
244245

t/lib/croak/class

+28
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,31 @@ class XXX {
185185
}
186186
EXPECT
187187
Cannot apply a :writer attribute to a non-scalar field at - line 6.
188+
########
189+
use v5.36;
190+
use feature 'class';
191+
no warnings 'experimental::class';
192+
sub f { last }
193+
class X {
194+
field $x = ::f();
195+
}
196+
# two warnings since we exit the initfields cv and f()
197+
X->new for 0;
198+
EXPECT
199+
Exiting subroutine via last at - line 4.
200+
Exiting subroutine via last at - line 4.
201+
Can't "last" outside a loop block at - line 4.
202+
########
203+
use v5.36;
204+
use feature 'class';
205+
no warnings 'experimental::class';
206+
class X {
207+
field $x;
208+
ADJUST {
209+
last;
210+
}
211+
}
212+
X->new for 0;
213+
EXPECT
214+
Exiting subroutine via last at - line 7.
215+
Can't "last" outside a loop block at - line 7.

0 commit comments

Comments
 (0)