commit a45358bf335c56f1a35b4cc9b9415633ed3e4bed Author: Petr Písař <ppisar@xxxxxxxxxx> 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@xxxxxxxx> +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@xxxxxxxx> +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@xxxxxxxxxxxxx> +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@xxxxxxxx> +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@xxxxxxxx> +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@xxxxxxxxxx> - 4:5.14.2-213 - Remove perl-devel dependency from perl-Test-Harness and perl-Test-Simple -- Fedora Extras Perl SIG http://www.fedoraproject.org/wiki/Extras/SIGs/Perl perl-devel mailing list perl-devel@xxxxxxxxxxxxxxxxxxxxxxx https://admin.fedoraproject.org/mailman/listinfo/perl-devel