Skip to content

Commit 9ffcdca

Browse files
author
Father Chrysostomos
committed
Don’t leak subs containing syntax errors
I fixed this for BEGIN blocks earlier, but missed the fact that all subs are affected. When called without an o argument (from newANONATTRSUB), newATTRSUB is expected to return a CV with an unowned reference count of which the caller will take ownership. We cannot have newATTRSUB returning a freed CV, so we have it return null instead. But that means ck_anoncode and pm_runtime have to account for that.
1 parent 12d3c23 commit 9ffcdca

File tree

2 files changed

+8
-5
lines changed

2 files changed

+8
-5
lines changed

op.c

+6-4
Original file line numberDiff line numberDiff line change
@@ -4650,7 +4650,7 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg, I32 floor)
46504650

46514651
/* attach the anon CV to the pad so that
46524652
* pad_fixup_inner_anons() can find it */
4653-
(void)pad_add_anon(cv, o->op_type);
4653+
if (cv) (void)pad_add_anon(cv, o->op_type);
46544654
SvREFCNT_inc_simple_void(cv);
46554655
}
46564656
else {
@@ -7370,15 +7370,14 @@ Perl_newATTRSUB_flags(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs,
73707370

73717371
if (ec) {
73727372
op_free(block);
7373-
cv = PL_compcv;
7373+
SvREFCNT_dec(PL_compcv);
7374+
PL_compcv = 0;
73747375
if (name && block) {
73757376
const char *s = strrchr(name, ':');
73767377
s = s ? s+1 : name;
73777378
if (strEQ(s, "BEGIN")) {
73787379
const char not_safe[] =
73797380
"BEGIN not safe after errors--compilation aborted";
7380-
PL_compcv = 0;
7381-
SvREFCNT_dec(cv);
73827381
if (PL_in_eval & EVAL_KEEPERR)
73837382
Perl_croak(aTHX_ not_safe);
73847383
else {
@@ -8176,6 +8175,9 @@ Perl_ck_anoncode(pTHX_ OP *o)
81768175
{
81778176
PERL_ARGS_ASSERT_CK_ANONCODE;
81788177

8178+
/* After errors, we won’t have any sub. */
8179+
if (!cSVOPo->op_sv) return o;
8180+
81798181
cSVOPo->op_targ = pad_add_anon((CV*)cSVOPo->op_sv, o->op_type);
81808182
if (!PL_madskills)
81818183
cSVOPo->op_sv = NULL;

t/op/svleak.t

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ BEGIN {
1515

1616
use Config;
1717

18-
plan tests => 64;
18+
plan tests => 65;
1919

2020
# run some code N times. If the number of SVs at the end of loop N is
2121
# greater than (N-1)*delta at the end of loop 1, we've got a leak
@@ -195,6 +195,7 @@ SKIP: {
195195
}
196196

197197
eleak(2, 0, '+sub:a{}', 'anon subs with invalid attributes');
198+
eleak(2, 0, 'no warnings; sub a{1 1}', 'sub with syntax error');
198199

199200
# Syntax errors
200201
eleak(2, 0, '"${<<END}"

0 commit comments

Comments
 (0)