summaryrefslogtreecommitdiff
path: root/sv.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2014-09-19 23:12:48 -0700
committerFather Chrysostomos <sprout@cpan.org>2014-09-20 09:25:02 -0700
commita623f8939cbcaa58a069807591675c0ebcd4135b (patch)
tree6e4f3122df0aefeac3b4eb007f9b869a850c6df9 /sv.c
parentfd01b4b766a3276a9439cade9b1a047c37876c1b (diff)
downloadperl-a623f8939cbcaa58a069807591675c0ebcd4135b.tar.gz
Implement the bipolar read-only system
This fixes bugs related to Hash::Util::unlock accidentally unlocking internal scalars (e.g., that returned by undef()) and allowing them to be modified. Internal read-only values are now marked by two flags, the regular read-only flag, and the new ‘protected’ flag. Before this SvREADONLY served two purposes: 1) The code would use it to protect things that must not be modi- fied, ever (except when the core sees fit to do so). 2) Hash::Util and everybody else would use it to make this unmodifia- ble temporarily when requested by the user. Internals::SvREADONLY serves the latter purpose and only flips the read-only flag, so things that need to stay read-only will remain so, because of the ‘other’ read-only flag, that CPAN doesn’t know about. (If you are a CPAN author, do not read this.)
Diffstat (limited to 'sv.c')
-rw-r--r--sv.c11
1 files changed, 6 insertions, 5 deletions
diff --git a/sv.c b/sv.c
index 8e88d31878..53b4f8bc05 100644
--- a/sv.c
+++ b/sv.c
@@ -4499,7 +4499,8 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, SV* sstr, const I32 flags)
/* slated for free anyway (and not COW)? */
(sflags & (SVs_TEMP|SVf_IsCOW)) == SVs_TEMP
/* or a swipable TARG */
- || ((sflags & (SVs_PADTMP|SVf_READONLY|SVf_IsCOW))
+ || ((sflags &
+ (SVs_PADTMP|SVf_READONLY|SVf_PROTECT|SVf_IsCOW))
== SVs_PADTMP
/* whose buffer is worth stealing */
&& CHECK_COWBUF_THRESHOLD(cur,len)
@@ -10071,7 +10072,7 @@ Perl_sv_bless(pTHX_ SV *const sv, HV *const stash)
if (!SvROK(sv))
Perl_croak(aTHX_ "Can't bless non-reference value");
tmpRef = SvRV(sv);
- if (SvFLAGS(tmpRef) & (SVs_OBJECT|SVf_READONLY)) {
+ if (SvFLAGS(tmpRef) & (SVs_OBJECT|SVf_READONLY|SVf_PROTECT)) {
if (SvREADONLY(tmpRef))
Perl_croak_no_modify();
if (SvOBJECT(tmpRef)) {
@@ -14875,18 +14876,18 @@ void
Perl_init_constants(pTHX)
{
SvREFCNT(&PL_sv_undef) = SvREFCNT_IMMORTAL;
- SvFLAGS(&PL_sv_undef) = SVf_READONLY|SVt_NULL;
+ SvFLAGS(&PL_sv_undef) = SVf_READONLY|SVf_PROTECT|SVt_NULL;
SvANY(&PL_sv_undef) = NULL;
SvANY(&PL_sv_no) = new_XPVNV();
SvREFCNT(&PL_sv_no) = SvREFCNT_IMMORTAL;
- SvFLAGS(&PL_sv_no) = SVt_PVNV|SVf_READONLY
+ SvFLAGS(&PL_sv_no) = SVt_PVNV|SVf_READONLY|SVf_PROTECT
|SVp_IOK|SVf_IOK|SVp_NOK|SVf_NOK
|SVp_POK|SVf_POK;
SvANY(&PL_sv_yes) = new_XPVNV();
SvREFCNT(&PL_sv_yes) = SvREFCNT_IMMORTAL;
- SvFLAGS(&PL_sv_yes) = SVt_PVNV|SVf_READONLY
+ SvFLAGS(&PL_sv_yes) = SVt_PVNV|SVf_READONLY|SVf_PROTECT
|SVp_IOK|SVf_IOK|SVp_NOK|SVf_NOK
|SVp_POK|SVf_POK;