diff options
author | Father Chrysostomos <sprout@cpan.org> | 2013-06-22 01:16:22 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2013-06-22 23:16:41 -0700 |
commit | 9b7d7782b9990e579acbba430d00797bfb529804 (patch) | |
tree | 43a98c0daea1f5833b6749f2cc2e943fff353e35 /pp_ctl.c | |
parent | ecff11eb0f000fc186c1b5652087c979947e4389 (diff) | |
download | perl-9b7d7782b9990e579acbba430d00797bfb529804.tar.gz |
Copy scalar refs returned from @INC filters
This commit:
4464f08ea532be08ea7f0c44d0eb6e285a0c36fb is the first bad commit
commit 4464f08ea532be08ea7f0c44d0eb6e285a0c36fb
Author: Nicholas Clark <nick@ccl4.org>
Date: Fri Oct 23 16:54:10 2009 +0100
S_run_user_filter() can use the filter GV itself for the cache buffer.
This saves allocating an extra SV head and body.
caused this:
$ perl -e '@INC = sub { \$_ }; eval { require foo }; $a = $_;'
Bizarre copy of IO in sassign at -e line 1.
Well, passing the existing string to filter_add causes that string
*itself* to be upgraded to SVt_PVIO, which is clearly not a good thing
if the caller can still reference it. So we end up with $ bound to an
IO thingy.
And if the referent is a REGEXP, we get a crash during global destruc-
tion, or at least we did until the previous commit, which stopped
REGEXP->PVIO upgrades from being legal. (Clearly they don’t work.)
The easiest way to fix this is to copy the string into a new scalar,
which then gets upgraded to PVIO.
Diffstat (limited to 'pp_ctl.c')
-rw-r--r-- | pp_ctl.c | 11 |
1 files changed, 5 insertions, 6 deletions
@@ -3842,7 +3842,6 @@ PP(pp_require) if (SvROK(arg) && (SvTYPE(SvRV(arg)) <= SVt_PVLV) && !isGV_with_GP(SvRV(arg))) { filter_cache = SvRV(arg); - SvREFCNT_inc_simple_void_NN(filter_cache); if (i < count) { arg = SP[i++]; @@ -3905,10 +3904,7 @@ PP(pp_require) } filter_has_file = 0; - if (filter_cache) { - SvREFCNT_dec(filter_cache); - filter_cache = NULL; - } + filter_cache = NULL; if (filter_state) { SvREFCNT_dec(filter_state); filter_state = NULL; @@ -4074,7 +4070,10 @@ PP(pp_require) than hanging another SV from it. In turn, filter_add() optionally takes the SV to use as the filter (or creates a new SV if passed NULL), so simply pass in whatever value filter_cache has. */ - SV * const datasv = filter_add(S_run_user_filter, filter_cache); + SV * const fc = filter_cache ? newSV(0) : NULL; + SV *datasv; + if (fc) sv_copypv(fc, filter_cache); + datasv = filter_add(S_run_user_filter, fc); IoLINES(datasv) = filter_has_file; IoTOP_GV(datasv) = MUTABLE_GV(filter_state); IoBOTTOM_GV(datasv) = MUTABLE_GV(filter_sub); |