From 1e4bec8baad75821acda2b42820cfdf492fe18dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= Date: Fri, 5 Apr 2019 17:40:24 +0200 Subject: [PATCH] Fix a memory leak when deletion in a tied hash dies --- ...29.9-avoid-leak-with-local-h-foo-a-n.patch | 108 ++++++++++++++++++ perl.spec | 6 + 2 files changed, 114 insertions(+) create mode 100644 perl-5.29.9-avoid-leak-with-local-h-foo-a-n.patch diff --git a/perl-5.29.9-avoid-leak-with-local-h-foo-a-n.patch b/perl-5.29.9-avoid-leak-with-local-h-foo-a-n.patch new file mode 100644 index 0000000..22ec2f2 --- /dev/null +++ b/perl-5.29.9-avoid-leak-with-local-h-foo-a-n.patch @@ -0,0 +1,108 @@ +From 85df897fcfe76250deecfdeb239ba1e4279d8532 Mon Sep 17 00:00:00 2001 +From: David Mitchell +Date: Tue, 26 Mar 2019 11:04:07 +0000 +Subject: [PATCH] avoid leak with local $h{foo}, $a[n] +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When SAVEt_DELETE / SAVEt_ADELETE deletes a hash/array entry on scope +exit, they also decrement the refcount of the hash/array, and for the +hash, also free the saved key. + +However, if the call to hv_delete() or av_delete() dies (e.g. when +calling a tied DELETE method) then the hash/array and key will leak +because leave_scope() calls av/hv_delete(), *then* does the +SvREFCNT_dec() etc. + +The fix is to push new FREEPV/FREESV actions just before calling +av/hv_delete(). + +Signed-off-by: Petr Písař +--- + scope.c | 17 ++++++++++++++--- + t/op/tie.t | 37 +++++++++++++++++++++++++++++++++++++ + 2 files changed, 51 insertions(+), 3 deletions(-) + +diff --git a/scope.c b/scope.c +index 83a7b76893..3e4ee4344b 100644 +--- a/scope.c ++++ b/scope.c +@@ -1253,15 +1253,26 @@ Perl_leave_scope(pTHX_ I32 base) + + case SAVEt_DELETE: + a0 = ap[0]; a1 = ap[1]; a2 = ap[2]; ++ /* hv_delete could die, so free the key and SvREFCNT_dec the ++ * hv by pushing new save actions ++ */ ++ /* ap[0] is the key */ ++ ap[1].any_uv = SAVEt_FREEPV; /* was len */ ++ /* ap[2] is the hv */ ++ ap[3].any_uv = SAVEt_FREESV; /* was SAVEt_DELETE */ ++ PL_savestack_ix += 4; + (void)hv_delete(a2.any_hv, a0.any_pv, a1.any_i32, G_DISCARD); +- SvREFCNT_dec(a2.any_hv); +- Safefree(a0.any_ptr); + break; + + case SAVEt_ADELETE: + a0 = ap[0]; a1 = ap[1]; ++ /* av_delete could die, so SvREFCNT_dec the av by pushing a ++ * new save action ++ */ ++ ap[0].any_av = a1.any_av; ++ ap[1].any_uv = SAVEt_FREESV; ++ PL_savestack_ix += 2; + (void)av_delete(a1.any_av, a0.any_iv, G_DISCARD); +- SvREFCNT_dec(a1.any_av); + break; + + case SAVEt_DESTRUCTOR_X: +diff --git a/t/op/tie.t b/t/op/tie.t +index a2d771a009..bfcafce87a 100644 +--- a/t/op/tie.t ++++ b/t/op/tie.t +@@ -1585,3 +1585,40 @@ print "[$x][$f][$n][$s]\n"; + EXPECT + [3][1][3][0] + [0][2][3][0] ++######## ++# dying while doing a SAVEt_DELETE dureing scope exit leaked a copy of the ++# key. Give ASan something to play with ++sub TIEHASH { bless({}, $_[0]) } ++sub EXISTS { 0 } ++sub DELETE { die; } ++sub DESTROY { print "destroy\n"; } ++ ++eval { ++ my %h; ++ tie %h, "main"; ++ local $h{foo}; ++ print "leaving\n"; ++}; ++print "left\n"; ++EXPECT ++leaving ++destroy ++left ++######## ++# ditto for SAVEt_DELETE with an array ++sub TIEARRAY { bless({}, $_[0]) } ++sub EXISTS { 0 } ++sub DELETE { die; } ++sub DESTROY { print "destroy\n"; } ++ ++eval { ++ my @a; ++ tie @a, "main"; ++ delete local $a[0]; ++ print "leaving\n"; ++}; ++print "left\n"; ++EXPECT ++leaving ++destroy ++left +-- +2.20.1 + diff --git a/perl.spec b/perl.spec index fc0e632..33686cf 100644 --- a/perl.spec +++ b/perl.spec @@ -299,6 +299,9 @@ Patch65: perl-5.28.1-fix-a-leak-with-indented-heredocs.patch Patch66: perl-5.29.9-fix-leak-in-package-name-lookup.patch Patch67: perl-5.29.9-Fix-recent-double-free-in-S_parse_gv_stash_name.patch +# Fix a memory leak when deletion in a tied hash dies, in upstream after 5.29.9 +Patch68: perl-5.29.9-avoid-leak-with-local-h-foo-a-n.patch + # Link XS modules to libperl.so with EU::CBuilder on Linux, bug #960048 Patch200: perl-5.16.3-Link-XS-modules-to-libperl.so-with-EU-CBuilder-on-Li.patch @@ -2922,6 +2925,7 @@ Perl extension for Version Objects %patch65 -p1 %patch66 -p1 %patch67 -p1 +%patch68 -p1 %patch200 -p1 %patch201 -p1 @@ -2980,6 +2984,7 @@ perl -x patchlevel.h \ 'Fedora Patch64: Fix a memory leak when assignig to a localized ${^WARNING_BITS}' \ 'Fedora Patch65: Fix a memory leak when parsing misindented here-documents' \ 'Fedora Patch66: Fix a memory leak in package name lookup (RT#133977)' \ + 'Fedora Patch68: Fix a memory leak when deletion in a tied hash dies' \ 'Fedora Patch200: Link XS modules to libperl.so with EU::CBuilder on Linux' \ 'Fedora Patch201: Link XS modules to libperl.so with EU::MM on Linux' \ %{nil} @@ -5280,6 +5285,7 @@ popd - Fix a memory leak when assignig to a localized ${^WARNING_BITS} - Fix a memory leak when parsing misindented here-documents - Fix a memory leak in package name lookup (RT#133977) +- Fix a memory leak when deletion in a tied hash dies * Tue Mar 05 2019 Björn Esser - 4:5.28.1-434 - Add explicit Requires: libxcrypt-devel to devel sub-package (bug #1666098)