diff options
author | David Mitchell <davem@iabyn.com> | 2015-09-21 14:49:22 +0100 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2015-10-02 11:29:35 +0100 |
commit | 052a7c766b9640ee847979cb9d2351a63e23a378 (patch) | |
tree | 1a796b916aa4702854196a5c6ef9767b4d6b98e8 /pp.c | |
parent | 6768377c79109b7124f0c8a4e3677982689d9f49 (diff) | |
download | perl-052a7c766b9640ee847979cb9d2351a63e23a378.tar.gz |
fix up EXTEND() callers
The previous commit made it clear that the N argument to EXTEND()
is supposed to be signed, in particular SSize_t, and now typically
triggers compiler warnings where this isn't the case.
This commit fixes the various places in core that passed the wrong sort of
N to EXTEND(). The fixes are in three broad categories.
First, where sensible, I've changed the relevant var to be SSize_t.
Second, where its expected that N could never be large enough to wrap,
I've just added an assert and a cast.
Finally, I've added extra code to detect whether the cast could
wrap/truncate, and if so set N to -1, which will trigger a panic in
stack_grow().
This also fixes
[perl #125937] 'x' operator on list causes segfault with possible
stack corruption
Diffstat (limited to 'pp.c')
-rw-r--r-- | pp.c | 29 |
1 files changed, 16 insertions, 13 deletions
@@ -88,18 +88,18 @@ PP(pp_padav) gimme = GIMME_V; if (gimme == G_ARRAY) { /* XXX see also S_pushav in pp_hot.c */ - const Size_t maxarg = AvFILL(MUTABLE_AV(TARG)) + 1; + const SSize_t maxarg = AvFILL(MUTABLE_AV(TARG)) + 1; EXTEND(SP, maxarg); if (SvMAGICAL(TARG)) { - Size_t i; + SSize_t i; for (i=0; i < maxarg; i++) { SV * const * const svp = av_fetch(MUTABLE_AV(TARG), i, FALSE); SP[i+1] = (svp) ? *svp : &PL_sv_undef; } } else { - PADOFFSET i; - for (i=0; i < (PADOFFSET)maxarg; i++) { + SSize_t i; + for (i=0; i < maxarg; i++) { SV * const sv = AvARRAY((const AV *)TARG)[i]; SP[i+1] = sv ? sv : &PL_sv_undef; } @@ -1718,14 +1718,15 @@ PP(pp_repeat) if (GIMME_V == G_ARRAY && PL_op->op_private & OPpREPEAT_DOLIST) { dMARK; - const Size_t items = SP - MARK; + const SSize_t items = SP - MARK; const U8 mod = PL_op->op_flags & OPf_MOD; if (count > 1) { - Size_t max; + SSize_t max; - if ( items > MEM_SIZE_MAX / (UV)count /* max would overflow */ - || items > (U32)I32_MAX / sizeof(SV *) /* repeatcpy would overflow */ + if ( items > SSize_t_MAX / count /* max would overflow */ + /* repeatcpy would overflow */ + || items > I32_MAX / (I32)sizeof(SV *) ) Perl_croak(aTHX_ "%s","Out of memory during list extend"); max = items * count; @@ -1746,7 +1747,7 @@ PP(pp_repeat) SP += max; } else if (count <= 0) - SP -= items; + SP = MARK; } else { /* Note: mark already snarfed by pp_list */ SV * const tmpstr = POPs; @@ -5660,7 +5661,7 @@ PP(pp_split) SSize_t maxiters = slen + 10; I32 trailing_empty = 0; const char *orig; - const I32 origlimit = limit; + const IV origlimit = limit; I32 realarray = 0; I32 base; const I32 gimme = GIMME_V; @@ -5834,11 +5835,13 @@ PP(pp_split) split //, $str, $i; */ if (!gimme_scalar) { - const U32 items = limit - 1; - if (items < slen) + const IV items = limit - 1; + /* setting it to -1 will trigger a panic in EXTEND() */ + const SSize_t sslen = slen > SSize_t_MAX ? -1 : (SSize_t)slen; + if (items >=0 && items < sslen) EXTEND(SP, items); else - EXTEND(SP, slen); + EXTEND(SP, sslen); } if (do_utf8) { |