diff options
author | Paul "LeoNerd" Evans <leonerd@leonerd.org.uk> | 2023-02-14 22:50:42 +0000 |
---|---|---|
committer | Paul Evans <leonerd@leonerd.org.uk> | 2023-02-17 21:06:16 +0000 |
commit | 04c0207ebb3cb7f894b5f5b6320970aabda477a9 (patch) | |
tree | eb8c26eb2998fb14f91d013b9a7a1618b3b8c7f6 /class.c | |
parent | 7da1927c007a205d378f1913ba5dd4027799926e (diff) | |
download | perl-04c0207ebb3cb7f894b5f5b6320970aabda477a9.tar.gz |
Fix a bunch of memory leaks in feature 'class'
* Free the attrlist OP fragment when applying class or field attribute
* Free the OP_PADxV ops we only use to get the pad index out for
fieldvar declarations
* Add a refcount to the `struct padname_fieldinfo` to keep track of its
capture in inner closures so it can be freed at the right time
* Free the class-related fields out of HvAUX
* Free the actual ObjectFIELDS() array when destroying an object instance
* Dup fieldinfo->paramname at sv_dup() time / free it at free time
Diffstat (limited to 'class.c')
-rw-r--r-- | class.c | 18 |
1 files changed, 17 insertions, 1 deletions
@@ -601,6 +601,13 @@ Perl_class_apply_attributes(pTHX_ HV *stash, OP *attrlist) { PERL_ARGS_ASSERT_CLASS_APPLY_ATTRIBUTES; + if(!attrlist) + return; + if(attrlist->op_type == OP_NULL) { + op_free(attrlist); + return; + } + if(attrlist->op_type == OP_LIST) { OP *o = cLISTOPx(attrlist)->op_first; assert(o->op_type == OP_PUSHMARK); @@ -611,6 +618,8 @@ Perl_class_apply_attributes(pTHX_ HV *stash, OP *attrlist) } else S_class_apply_attribute(aTHX_ stash, attrlist); + + op_free(attrlist); } static OP * @@ -892,6 +901,7 @@ Perl_class_add_field(pTHX_ HV *stash, PADNAME *pn) Newxz(PadnameFIELDINFO(pn), 1, struct padname_fieldinfo); PadnameFLAGS(pn) |= PADNAMEf_FIELD; + PadnameFIELDINFO(pn)->refcount = 1; PadnameFIELDINFO(pn)->fieldix = fieldix; PadnameFIELDINFO(pn)->fieldstash = (HV *)SvREFCNT_inc(stash); @@ -972,8 +982,12 @@ Perl_class_apply_field_attributes(pTHX_ PADNAME *pn, OP *attrlist) { PERL_ARGS_ASSERT_CLASS_APPLY_FIELD_ATTRIBUTES; - if(!attrlist || attrlist->op_type == OP_NULL) + if(!attrlist) + return; + if(attrlist->op_type == OP_NULL) { + op_free(attrlist); return; + } if(attrlist->op_type == OP_LIST) { OP *o = cLISTOPx(attrlist)->op_first; @@ -985,6 +999,8 @@ Perl_class_apply_field_attributes(pTHX_ PADNAME *pn, OP *attrlist) } else S_class_apply_field_attribute(aTHX_ pn, attrlist); + + op_free(attrlist); } void |