summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scope.c7
-rw-r--r--t/comp/hints.t25
2 files changed, 27 insertions, 5 deletions
diff --git a/scope.c b/scope.c
index cc207c089c..1bf79e0227 100644
--- a/scope.c
+++ b/scope.c
@@ -1024,8 +1024,9 @@ Perl_leave_scope(pTHX_ I32 base)
break;
case SAVEt_HINTS:
if ((PL_hints & HINT_LOCALIZE_HH) && GvHV(PL_hintgv)) {
- SvREFCNT_dec(MUTABLE_SV(GvHV(PL_hintgv)));
+ HV *hv = GvHV(PL_hintgv);
GvHV(PL_hintgv) = NULL;
+ SvREFCNT_dec(MUTABLE_SV(hv));
}
cophh_free(CopHINTHASH_get(&PL_compiling));
CopHINTHASH_set(&PL_compiling, (COPHH*)SSPOPPTR);
@@ -1033,8 +1034,8 @@ Perl_leave_scope(pTHX_ I32 base)
if (PL_hints & HINT_LOCALIZE_HH) {
SvREFCNT_dec(MUTABLE_SV(GvHV(PL_hintgv)));
GvHV(PL_hintgv) = MUTABLE_HV(SSPOPPTR);
- assert(GvHV(PL_hintgv));
- } else if (!GvHV(PL_hintgv)) {
+ }
+ if (!GvHV(PL_hintgv)) {
/* Need to add a new one manually, else gv_fetchpv() can
add one in this code:
diff --git a/t/comp/hints.t b/t/comp/hints.t
index 8401ec9436..d22b15e9d1 100644
--- a/t/comp/hints.t
+++ b/t/comp/hints.t
@@ -6,7 +6,7 @@ BEGIN {
@INC = qw(. ../lib);
}
-BEGIN { print "1..29\n"; }
+BEGIN { print "1..30\n"; }
BEGIN {
print "not " if exists $^H{foo};
print "ok 1 - \$^H{foo} doesn't exist initially\n";
@@ -216,6 +216,27 @@ print "ok 26 - no crash when cloning a tied hint hash\n";
"setting \${^WARNING_BITS} to its own value has no effect\n";
}
+# [perl #112326]
+# this code could cause a crash, due to PL_hints continuing to point to th
+# hints hash currently being freed
+
+{
+ package Foo;
+ my @h = qw(a 1 b 2);
+ BEGIN {
+ $^H{FOO} = bless {};
+ }
+ sub DESTROY {
+ @h = %^H;
+ delete $INC{strict}; require strict; # boom!
+ }
+ my $h = join ':', %h;
+ # this isn't the main point of the test; the main point is that
+ # it doesn't crash!
+ print "not " if $h ne '';
+ print "ok 29 - #112326\n";
+}
+
# Add new tests above this require, in case it fails.
require './test.pl';
@@ -226,7 +247,7 @@ my $result = runperl(
stderr => 1
);
print "not " if length $result;
-print "ok 29 - double-freeing hints hash\n";
+print "ok 30 - double-freeing hints hash\n";
print "# got: $result\n" if length $result;
__END__