d35ea2
From 5f41fa466a67b5535aa8bcf4b814f242545ac7bd Mon Sep 17 00:00:00 2001
d35ea2
From: Karl Williamson <khw@cpan.org>
d35ea2
Date: Sat, 27 Feb 2021 11:43:41 -0700
d35ea2
Subject: [PATCH] regcomp.c: Remove memory leak
d35ea2
MIME-Version: 1.0
d35ea2
Content-Type: text/plain; charset=UTF-8
d35ea2
Content-Transfer-Encoding: 8bit
d35ea2
d35ea2
This fixes GH #18604.  There was a path through the code where a
d35ea2
particular SV did not get its reference count decremented.
d35ea2
d35ea2
I did an audit of the function and came up with several other
d35ea2
possiblities that are included in this commit.
d35ea2
d35ea2
Further, there would be leaks for some instances of finding syntax
d35ea2
errors in the input pattern, or when warnings are fatalized.  Those
d35ea2
would require mortalizing some SVs, but that is beyond the scope of this
d35ea2
commit.
d35ea2
d35ea2
Signed-off-by: Petr Písař <ppisar@redhat.com>
d35ea2
---
d35ea2
 regcomp.c     | 7 +++++++
d35ea2
 t/op/svleak.t | 3 ++-
d35ea2
 2 files changed, 9 insertions(+), 1 deletion(-)
d35ea2
d35ea2
diff --git a/regcomp.c b/regcomp.c
d35ea2
index e44c7a37e5..f5e5f581dc 100644
d35ea2
--- a/regcomp.c
d35ea2
+++ b/regcomp.c
d35ea2
@@ -18765,6 +18765,12 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth,
d35ea2
 	RExC_end = save_end;
d35ea2
 	RExC_in_multi_char_class = 0;
d35ea2
         SvREFCNT_dec_NN(multi_char_matches);
d35ea2
+        SvREFCNT_dec(properties);
d35ea2
+        SvREFCNT_dec(cp_list);
d35ea2
+        SvREFCNT_dec(simple_posixes);
d35ea2
+        SvREFCNT_dec(posixes);
d35ea2
+        SvREFCNT_dec(nposixes);
d35ea2
+        SvREFCNT_dec(cp_foldable_list);
d35ea2
         return ret;
d35ea2
     }
d35ea2
 
d35ea2
@@ -20122,6 +20128,7 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth,
d35ea2
                                            RExC_parse - orig_parse);;
d35ea2
     SvREFCNT_dec(cp_list);;
d35ea2
     SvREFCNT_dec(only_utf8_locale_list);
d35ea2
+    SvREFCNT_dec(upper_latin1_only_utf8_matches);
d35ea2
     return ret;
d35ea2
 }
d35ea2
 
d35ea2
diff --git a/t/op/svleak.t b/t/op/svleak.t
d35ea2
index 6acc298c3d..3df4838be8 100644
d35ea2
--- a/t/op/svleak.t
d35ea2
+++ b/t/op/svleak.t
d35ea2
@@ -15,7 +15,7 @@ BEGIN {
d35ea2
 
d35ea2
 use Config;
d35ea2
 
d35ea2
-plan tests => 150;
d35ea2
+plan tests => 151;
d35ea2
 
d35ea2
 # run some code N times. If the number of SVs at the end of loop N is
d35ea2
 # greater than (N-1)*delta at the end of loop 1, we've got a leak
d35ea2
@@ -278,6 +278,7 @@ eleak(2,0,'/[[:ascii:]]/');
d35ea2
 eleak(2,0,'/[[.zog.]]/');
d35ea2
 eleak(2,0,'/[.zog.]/');
d35ea2
 eleak(2,0,'/|\W/', '/|\W/ [perl #123198]');
d35ea2
+eleak(2,0,'/a\sb/', '/a\sb/ [GH #18604]');
d35ea2
 eleak(2,0,'no warnings; /(?[])/');
d35ea2
 eleak(2,0,'no warnings; /(?[[a]+[b]])/');
d35ea2
 eleak(2,0,'no warnings; /(?[[a]-[b]])/');
d35ea2
-- 
d35ea2
2.26.2
d35ea2