[perl/f17] Free hash entries before values on delete

Petr Pisar ppisar at fedoraproject.org
Tue Sep 11 16:25:21 UTC 2012


commit a45358bf335c56f1a35b4cc9b9415633ed3e4bed
Author: Petr Písař <ppisar at redhat.com>
Date:   Tue Sep 11 16:50:42 2012 +0200

    Free hash entries before values on delete

 ...-Free-hash-entries-before-values-on-delet.patch |  170 ++++++++++++++++++++
 perl.spec                                          |    6 +
 2 files changed, 176 insertions(+), 0 deletions(-)
---
diff --git a/perl-5.14.2-perl-100340-Free-hash-entries-before-values-on-delet.patch b/perl-5.14.2-perl-100340-Free-hash-entries-before-values-on-delet.patch
new file mode 100644
index 0000000..e1de801
--- /dev/null
+++ b/perl-5.14.2-perl-100340-Free-hash-entries-before-values-on-delet.patch
@@ -0,0 +1,170 @@
+From 9eee62a53e8ec6881d4e6943be983b6486c78ce7 Mon Sep 17 00:00:00 2001
+From: Father Chrysostomos <sprout at cpan.org>
+Date: Sat, 31 Dec 2011 18:54:14 -0800
+Subject: [PATCH] Free hash entries before values on delete
+
+Petr Pisar: Ported for 5.14.2:
+
+From 3b2cd8095a6fc52afccf519205a3c5a92669b0c3 Mon Sep 17 00:00:00 2001
+From: Father Chrysostomos <sprout at cpan.org>
+Date: Sat, 31 Dec 2011 18:54:14 -0800
+Subject: [PATCH] [perl #100340] Free hash entries before values on delete
+
+When a hash element is deleted in void context, if the value is freed
+before the hash entry, it is possible for a destructor to see the hash
+in an inconsistent state--inconsistent in that it contains entries
+that are about to be freed, with nothing to indicate that.  So the
+destructor itself could free the very same hash entry (e.g., by
+freeing the hash), resulting in a double free, panic, or other
+unpleasantness.
+
+Petr Pisar: A few lines borrowed from:
+
+commit f50383f58716bc0faa50de094d47cad8ad3fcbdb
+Author: Ton Hospel <me-02 at ton.iguana.be>
+Date:   Thu May 19 17:05:16 2011 -0700
+
+    [perl #85026] Deleting the current iterator in void context
+
+and
+
+commit 705822126c5e218f2fe40097f9f1a204474e864b
+Author: Father Chrysostomos <sprout at cpan.org>
+Date:   Wed Sep 21 00:59:02 2011 -0700
+
+    [perl #99660] Remove elems from hashes before freeing them
+
+and
+
+commit 5743f2a37eb9fda061f42b2df6b4c8119b14eaf1
+Author: Father Chrysostomos <sprout at cpan.org>
+Date:   Sat Dec 31 18:18:57 2011 -0800
+
+    Update method caches for non-void stash elem deletions
+---
+ hv.c          | 19 +++++++++++++++----
+ t/op/hash.t   | 30 +++++++++++++++++++++++++++++-
+ t/op/method.t |  7 ++++++-
+ 3 files changed, 50 insertions(+), 6 deletions(-)
+
+diff --git a/hv.c b/hv.c
+index 2be1feb..8731dbd 100644
+--- a/hv.c
++++ b/hv.c
+@@ -1050,12 +1050,20 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen,
+ 		    mro_changes = 1;
+ 	}
+ 
+-	if (d_flags & G_DISCARD)
+-	    sv = NULL;
++	if (d_flags & G_DISCARD) {
++	    sv = HeVAL(entry);
++	    HeVAL(entry) = &PL_sv_placeholder;
++	}
+ 	else {
+ 	    sv = sv_2mortal(HeVAL(entry));
+ 	    HeVAL(entry) = &PL_sv_placeholder;
+ 	}
++	if (sv) {
++	    /* deletion of method from stash */
++	    if (isGV(sv) && isGV_with_GP(sv) && GvCVu(sv)
++	     && HvENAME_get(hv))
++		mro_method_changed_in(hv);
++	}
+ 
+ 	/*
+ 	 * If a restricted hash, rather than really deleting the entry, put
+@@ -1064,8 +1072,6 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen,
+ 	 * an error.
+ 	 */
+ 	if (SvREADONLY(hv)) {
+-	    SvREFCNT_dec(HeVAL(entry));
+-	    HeVAL(entry) = &PL_sv_placeholder;
+ 	    /* We'll be saving this slot, so the number of allocated keys
+ 	     * doesn't go down, but the number placeholders goes up */
+ 	    HvPLACEHOLDERS(hv)++;
+@@ -1084,6 +1090,11 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen,
+ 	        HvHASKFLAGS_off(hv);
+ 	}
+ 
++	if (d_flags & G_DISCARD) {
++	    SvREFCNT_dec(sv);
++	    sv = NULL;
++	}
++
+ 	if (mro_changes == 1) mro_isa_changed_in(hv);
+ 	else if (mro_changes == 2)
+ 	    mro_package_moved(NULL, stash, gv, 1);
+diff --git a/t/op/hash.t b/t/op/hash.t
+index 278bea7..cb2667b 100644
+--- a/t/op/hash.t
++++ b/t/op/hash.t
+@@ -8,7 +8,7 @@ BEGIN {
+ 
+ use strict;
+ 
+-plan tests => 8;
++plan tests => 10;
+ 
+ my %h;
+ 
+@@ -146,3 +146,31 @@ is($destroyed, 1, 'Timely hash destruction with lvalue keys');
+     is ref $key, SCALAR =>
+      'hash keys are not stringified during compilation';
+ }
++
++# [perl #100340] Similar bug: freeing a hash elem during a delete
++sub guard::DESTROY {
++   ${$_[0]}->();
++};
++*guard = sub (&) {
++   my $callback = shift;
++   return bless \$callback, "guard"
++};
++{
++  my $ok;
++  my %t; %t = (
++    stash => {
++        guard => guard(sub{
++            $ok++;
++            delete $t{stash};
++        }),
++        foo => "bar",
++        bar => "baz",
++    },
++  );
++  ok eval { delete $t{stash}{guard}; # must be in void context
++            1 },
++    'freeing a hash elem from destructor called by delete does not die';
++  diag $@ if $@; # panic: free from wrong pool
++  is $ok, 1, 'the destructor was called';
++}
++
+diff --git a/t/op/method.t b/t/op/method.t
+index 3c00542..22ff53b 100644
+--- a/t/op/method.t
++++ b/t/op/method.t
+@@ -13,7 +13,7 @@ BEGIN {
+ use strict;
+ no warnings 'once';
+ 
+-plan(tests => 79);
++plan(tests => 80);
+ 
+ @A::ISA = 'B';
+ @B::ISA = 'C';
+@@ -85,6 +85,11 @@ is(A->d, "B::d2");		# Update hash table;
+ 
+ undef &B::d;
+ delete $B::{d};
++is(A->d, "C::d");
++
++eval 'sub B::d {"B::d2.5"}';
++A->d;                          # Update hash table;
++my $glob = \delete $B::{d};    # non-void context; hang on to the glob
+ is(A->d, "C::d");		# Update hash table;
+ 
+ eval 'sub B::d {"B::d3"}';	# Import now.
+-- 
+1.7.11.4
+
diff --git a/perl.spec b/perl.spec
index 3542868..dae9f23 100644
--- a/perl.spec
+++ b/perl.spec
@@ -107,6 +107,9 @@ Patch18:        perl-5.16.1-perl-113980-pp_syscall-I32-retval-truncates-the-retu
 # Match starting byte in non-UTF-8 mode, rhbz#801739, RT#101710
 Patch19:        perl-5.14.2-PATCH-perl-101710-Regression-with-i-latin1-chars.patch
 
+# Free hash entries before values on delete, rhbz#771303, RT#100340
+Patch20:        perl-5.14.2-perl-100340-Free-hash-entries-before-values-on-delet.patch
+
 # Update some of the bundled modules
 # see http://fedoraproject.org/wiki/Perl/perl.spec for instructions
 
@@ -1277,6 +1280,7 @@ tarball from perl.org.
 %patch17 -p1
 %patch18 -p1
 %patch19 -p1
+%patch20 -p1
 
 #copy the example script
 cp -a %{SOURCE5} .
@@ -1486,6 +1490,7 @@ pushd %{build_archlib}/CORE/
     'Fedora Patch17: Clear $@ before "do" I/O error (RT#113730)' \
     'Fedora Patch18: Do not truncate syscall() return value to 32 bits (RT#113980)' \
     'Fedora Patch19: Match starting byte in non-UTF-8 mode (RT#101710)' \
+    'Fedora Patch20: Free hash entries before values on delete (RT#100340)' \
     %{nil}
 
 rm patchlevel.bak
@@ -2441,6 +2446,7 @@ sed \
 - Clear $@ before `do' I/O error (bug #834226)
 - Do not truncate syscall() return value to 32 bits (bug #838551)
 - Match starting byte in non-UTF-8 mode (bug #801739)
+- Free hash entries before values on delete (bug #771303)
 
 * Wed Sep 05 2012 Petr Pisar <ppisar at redhat.com> - 4:5.14.2-213
 - Remove perl-devel dependency from perl-Test-Harness and perl-Test-Simple


More information about the scm-commits mailing list