summaryrefslogtreecommitdiff
path: root/pp_ctl.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2013-08-07 18:21:00 -0700
committerFather Chrysostomos <sprout@cpan.org>2013-08-09 19:28:34 -0700
commit9e0ea7f366b3255bc81b5cd80758673bf421604c (patch)
tree6ef85fe41a0fd104e85ba02ff805a70283efc20e /pp_ctl.c
parentfff2dea573c6a4eadf4c2df969590ce0b48e1777 (diff)
downloadperl-9e0ea7f366b3255bc81b5cd80758673bf421604c.tar.gz
Avoid assert fail with s// $target = \3 /e
When the substitution target is assigned to in pp_substcont, it is assumed that SvPV_free and SvPOK_only_UTF8 can be used on that target. Only COW scalars are sent through sv_force_normal. Changing the target in the replacement code can render those assump- tions untrue: $ ./perl -Ilib -e '$h = 3; $h =~ s/3/$h=\3;4/e' Assertion failed: (!((targ)->sv_flags & 0x00000800) || !(*({ SV *const _svrv = ((SV *)({ void *_p = (targ); _p; })); (__builtin_expect(!(PL_valid_types_RV[((svtype)((_svrv)->sv_flags & 0xff)) & 0xf]), 0) ? __assert_rtn(__func__, "pp_ctl.c", 269, "PL_valid_types_RV[SvTYPE(_svrv) & SVt_MASK]") : (void)0); (__builtin_expect(!(!((((_svrv)->sv_flags & (0x00004000|0x00008000)) == 0x00008000) && (((svtype)((_svrv)->sv_flags & 0xff)) == SVt_PVGV || ((svtype)((_svrv)->sv_flags & 0xff)) == SVt_PVLV))), 0) ? __assert_rtn(__func__, "pp_ctl.c", 269, "!isGV_with_GP(_svrv)") : (void)0); (__builtin_expect(!(!(((svtype)((_svrv)->sv_flags & 0xff)) == SVt_PVIO && !(((XPVIO*) (_svrv)->sv_any)->xio_flags & 64))), 0) ? __assert_rtn(__func__, "pp_ctl.c", 269, "!(SvTYPE(_svrv) == SVt_PVIO && !(IoFLAGS(_svrv) & IOf_FAKE_DIRP))") : (void)0); &((_svrv)->sv_u.svu_rv); }))), function Perl_pp_substcont, file pp_ctl.c, line 269. Abort trap: 6 Also, matching against a hash key and locking that key with Hash::Util within the replacement code can cause the substitution to modify that hash key without triggering ‘Modification of a read-only value’. But this only happens if it is not a copy-on-write scalar: $ ./perl -Ilib -MHash::Util=lock_hash -le '$h{foo} = 3; $h{foo} =~ s/3/$h{foo} = 3; lock_hash %h; 4/e; print $h{foo}' 4 We need to do a regular SV_THINKFIRST_COW_DROP check here, just as we do in sv_setsv with regular scalar assignment. Also, we need to take into account real globs: $ ./perl -Ilib -MHash::Util=lock_hash -le '$::{foo} =~ s//*{"foo"}; 4/e' Assertion failed: (!isGV_with_GP(targ)), function Perl_pp_substcont, file pp_ctl.c, line 259. Abort trap: 6
Diffstat (limited to 'pp_ctl.c')
-rw-r--r--pp_ctl.c9
1 files changed, 3 insertions, 6 deletions
diff --git a/pp_ctl.c b/pp_ctl.c
index 1f9432b9f6..85149fe2f3 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -250,12 +250,9 @@ PP(pp_substcont)
targ = dstr;
}
else {
- if (SvIsCOW(targ)) {
- sv_force_normal_flags(targ, SV_COW_DROP_PV);
- } else
- {
- SvPV_free(targ);
- }
+ SV_CHECK_THINKFIRST_COW_DROP(targ);
+ if (isGV(targ)) Perl_croak_no_modify();
+ SvPV_free(targ);
SvPV_set(targ, SvPVX(dstr));
SvCUR_set(targ, SvCUR(dstr));
SvLEN_set(targ, SvLEN(dstr));