Skip to content

Commit 5a1dfa4

Browse files
committed
class: don't leak the default initialiser ops if they're forbidden
Previously if forbid_outofblock_ops() here threw an error the ops from defop would leak, including leaking the slab(s) containing those ops. The other callers to forbid_outofblock_ops() left the ops being checked on the parser stack when performing this check, so the parse stack clean up would release the ops, but the field initaliser code removes the OP from the parse stack before class_set_field_defop() so the OP and its children leaked. To prevent that, populate the defop for the field with the supplied ops before calling forbid_outofblock_ops(), then as the stack rewinds class_seal_stash() will check the error count and free the ops. Fixes Perl#20812
1 parent ff34800 commit 5a1dfa4

File tree

1 file changed

+17
-4
lines changed

1 file changed

+17
-4
lines changed

class.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -635,8 +635,8 @@ Perl_class_seal_stash(pTHX_ HV *stash)
635635
assert(HvSTASH_IS_CLASS(stash));
636636
struct xpvhv_aux *aux = HvAUX(stash);
637637

638-
/* generate initfields CV */
639-
{
638+
if (PL_parser->error_count) {
639+
/* generate initfields CV */
640640
I32 floor_ix = PL_savestack_ix;
641641
SAVEI32(PL_subline);
642642
save_item(PL_subname);
@@ -795,6 +795,16 @@ Perl_class_seal_stash(pTHX_ HV *stash)
795795

796796
aux->xhv_class_initfields_cv = initfields;
797797
}
798+
else {
799+
/* we had errors, clean up and don't populate initfields */
800+
PADNAMELIST *fieldnames = aux->xhv_class_fields;
801+
for(SSize_t i = 0; fieldnames && i <= PadnamelistMAX(fieldnames); i++) {
802+
PADNAME *pn = PadnamelistARRAY(fieldnames)[i];
803+
OP *valop = PadnameFIELDINFO(pn)->defop;
804+
if (valop)
805+
op_free(valop);
806+
}
807+
}
798808
}
799809

800810
void
@@ -1011,11 +1021,14 @@ Perl_class_set_field_defop(pTHX_ PADNAME *pn, OPCODE defmode, OP *defop)
10111021

10121022
assert(HvSTASH_IS_CLASS(PL_curstash));
10131023

1014-
forbid_outofblock_ops(defop, "field initialiser expression");
1015-
10161024
if(PadnameFIELDINFO(pn)->defop)
10171025
op_free(PadnameFIELDINFO(pn)->defop);
10181026

1027+
/* set here to ensure clean up if forbid_outofblock_ops() throws */
1028+
PadnameFIELDINFO(pn)->defop = defop;
1029+
1030+
forbid_outofblock_ops(defop, "field initialiser expression");
1031+
10191032
char sigil = PadnamePV(pn)[0];
10201033
switch(sigil) {
10211034
case '$':

0 commit comments

Comments
 (0)