diff options
author | Father Chrysostomos <sprout@cpan.org> | 2011-12-21 12:29:12 -0800 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2011-12-21 12:29:12 -0800 |
commit | cb1f05e8fe9a1c7a7e2de8048f1404df951311b0 (patch) | |
tree | 1e0379edd15719969f7492938c3b792f7f95824b | |
parent | fd20f1ec3b10f199361e00cffbe2406c485843fb (diff) | |
download | perl-cb1f05e8fe9a1c7a7e2de8048f1404df951311b0.tar.gz |
Copy hints from tied hh to inner compile scopes
Entries from a tied %^H were not being copied to inner compile-time
scopes, resulting in %^H appearing empty in BEGIN blocks, even
though the underlying he chain *was* being propagated properly (so
(caller)[10] at run time still worked.
I was surprised that, in writing tests for this, I produced another
crash. I thought I had fixed them with 95cf23680 and 7ef9d42ce. It
turns out that pp_helem doesn’t support hashes with null values.
(That’s a separate bug that needs fixing, since the XS API allows for
them.) For now, cloning the hh properly stops pp_helem from getting a
null value.
-rw-r--r-- | hv.c | 4 | ||||
-rw-r--r-- | t/comp/hints.t | 31 |
2 files changed, 27 insertions, 8 deletions
@@ -1450,7 +1450,7 @@ Perl_hv_copy_hints_hv(pTHX_ HV *const ohv) { HV * const hv = newHV(); - if (ohv && HvTOTALKEYS(ohv)) { + if (ohv) { STRLEN hv_max = HvMAX(ohv); STRLEN hv_fill = HvFILL(ohv); HE *entry; @@ -1463,7 +1463,7 @@ Perl_hv_copy_hints_hv(pTHX_ HV *const ohv) hv_iterinit(ohv); while ((entry = hv_iternext_flags(ohv, 0))) { - SV *const sv = newSVsv(HeVAL(entry)); + SV *const sv = newSVsv(hv_iterval(ohv,entry)); SV *heksv = HeSVKEY(entry); if (!heksv && sv) heksv = newSVhek(HeKEY_hek(entry)); if (sv) sv_magic(sv, NULL, PERL_MAGIC_hintselem, diff --git a/t/comp/hints.t b/t/comp/hints.t index b70f15eab1..15fbc5a13f 100644 --- a/t/comp/hints.t +++ b/t/comp/hints.t @@ -6,7 +6,7 @@ BEGIN { @INC = qw(. ../lib); } -BEGIN { print "1..25\n"; } +BEGIN { print "1..27\n"; } BEGIN { print "not " if exists $^H{foo}; print "ok 1 - \$^H{foo} doesn't exist initially\n"; @@ -129,7 +129,9 @@ BEGIN { } # [perl #106282] Crash when tying %^H -# Tying %^H does not and cannot work, but it should not crash. +# Tying %^H should not result in a crash when the hint hash is cloned. +# Hints should also be copied properly to inner scopes. See also +# [rt.cpan.org #73402]. eval q` # Do something naughty enough, and you get your module mentioned in the # test suite. :-) @@ -148,9 +150,26 @@ eval q` tie( %^H, 'namespace::clean::_TieHintHash' ); # sabotage %^H $^H{foo} = "bar"; # create an element in the tied hash } - { ; } # clone the tied hint hash -`; -print "ok 24 - no crash when cloning a tied hint hash\n"; + { # clone the tied hint hash on scope entry + BEGIN { + print "not " x ($^H{foo} ne 'bar'), + "ok 24 - tied hint hash is copied to inner scope\n"; + %^H = (); + tie( %^H, 'namespace::clean::_TieHintHash' ); + $^H{foo} = "bar"; + } + { + BEGIN{ + print + "not " x ($^H{foo} ne 'bar'), + "ok 25 - tied empty hint hash is copied to inner scope\n" + } + } + 1; + } + 1; +` or warn $@; +print "ok 26 - no crash when cloning a tied hint hash\n"; # Add new tests above this require, in case it fails. @@ -162,7 +181,7 @@ my $result = runperl( stderr => 1 ); print "not " if length $result; -print "ok 25 - double-freeing hints hash\n"; +print "ok 27 - double-freeing hints hash\n"; print "# got: $result\n" if length $result; __END__ |