[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