This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
regcomp.c: Remove memory leak
authorKarl Williamson <khw@cpan.org>
Sat, 27 Feb 2021 18:43:41 +0000 (11:43 -0700)
committerKarl Williamson <khw@cpan.org>
Sun, 28 Feb 2021 15:14:03 +0000 (08:14 -0700)
This fixes GH #18604.  There was a path through the code where a
particular SV did not get its reference count decremented.

I did an audit of the function and came up with several other
possiblities that are included in this commit.

Further, there would be leaks for some instances of finding syntax
errors in the input pattern, or when warnings are fatalized.  Those
would require mortalizing some SVs, but that is beyond the scope of this
commit.

regcomp.c
t/op/svleak.t

index e44c7a3..f5e5f58 100644 (file)
--- a/regcomp.c
+++ b/regcomp.c
@@ -18765,6 +18765,12 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth,
        RExC_end = save_end;
        RExC_in_multi_char_class = 0;
         SvREFCNT_dec_NN(multi_char_matches);
+        SvREFCNT_dec(properties);
+        SvREFCNT_dec(cp_list);
+        SvREFCNT_dec(simple_posixes);
+        SvREFCNT_dec(posixes);
+        SvREFCNT_dec(nposixes);
+        SvREFCNT_dec(cp_foldable_list);
         return ret;
     }
 
@@ -20122,6 +20128,7 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth,
                                            RExC_parse - orig_parse);;
     SvREFCNT_dec(cp_list);;
     SvREFCNT_dec(only_utf8_locale_list);
+    SvREFCNT_dec(upper_latin1_only_utf8_matches);
     return ret;
 }
 
index 6acc298..3df4838 100644 (file)
@@ -15,7 +15,7 @@ BEGIN {
 
 use Config;
 
-plan tests => 150;
+plan tests => 151;
 
 # run some code N times. If the number of SVs at the end of loop N is
 # greater than (N-1)*delta at the end of loop 1, we've got a leak
@@ -278,6 +278,7 @@ eleak(2,0,'/[[:ascii:]]/');
 eleak(2,0,'/[[.zog.]]/');
 eleak(2,0,'/[.zog.]/');
 eleak(2,0,'/|\W/', '/|\W/ [perl #123198]');
+eleak(2,0,'/a\sb/', '/a\sb/ [GH #18604]');
 eleak(2,0,'no warnings; /(?[])/');
 eleak(2,0,'no warnings; /(?[[a]+[b]])/');
 eleak(2,0,'no warnings; /(?[[a]-[b]])/');