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 /pad.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 'pad.c')
-rw-r--r-- | pad.c | 15 |
1 files changed, 14 insertions, 1 deletions
@@ -2803,6 +2803,7 @@ Perl_newPADNAMEouter(PADNAME *outer) PadnameFLAGS(pn) = PADNAMEf_OUTER; if(PadnameIsFIELD(outer)) { PadnameFIELDINFO(pn) = PadnameFIELDINFO(outer); + PadnameFIELDINFO(pn)->refcount++; PadnameFLAGS(pn) |= PADNAMEf_FIELD; } PadnameLEN(pn) = PadnameLEN(outer); @@ -2822,6 +2823,16 @@ Perl_padname_free(pTHX_ PADNAME *pn) SvREFCNT_dec(PadnameOURSTASH(pn)); if (PadnameOUTER(pn)) PadnameREFCNT_dec(PADNAME_FROM_PV(PadnamePV(pn))); + if (PadnameIsFIELD(pn)) { + struct padname_fieldinfo *info = PadnameFIELDINFO(pn); + if(!--info->refcount) { + SvREFCNT_dec(info->fieldstash); + /* todo: something about defop */ + SvREFCNT_dec(info->paramname); + + Safefree(info); + } + } Safefree(pn); } } @@ -2864,13 +2875,15 @@ Perl_padname_dup(pTHX_ PADNAME *src, CLONE_PARAMS *param) PadnameTYPE (dst) = (HV *)sv_dup_inc((SV *)PadnameTYPE(src), param); PadnameOURSTASH(dst) = (HV *)sv_dup_inc((SV *)PadnameOURSTASH(src), param); - if(PadnameIsFIELD(src)) { + if(PadnameIsFIELD(src) && !PadnameOUTER(src)) { struct padname_fieldinfo *sinfo = PadnameFIELDINFO(src); struct padname_fieldinfo *dinfo; Newxz(dinfo, 1, struct padname_fieldinfo); + dinfo->refcount = 1; dinfo->fieldix = sinfo->fieldix; dinfo->fieldstash = hv_dup_inc(sinfo->fieldstash, param); + dinfo->paramname = sv_dup_inc(sinfo->paramname, param); PadnameFIELDINFO(dst) = dinfo; } |