diff options
author | Father Chrysostomos <sprout@cpan.org> | 2013-08-07 18:21:00 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2013-08-09 19:28:34 -0700 |
commit | 9e0ea7f366b3255bc81b5cd80758673bf421604c (patch) | |
tree | 6ef85fe41a0fd104e85ba02ff805a70283efc20e /pp_ctl.c | |
parent | fff2dea573c6a4eadf4c2df969590ce0b48e1777 (diff) | |
download | perl-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.c | 9 |
1 files changed, 3 insertions, 6 deletions
@@ -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)); |