summaryrefslogtreecommitdiff
path: root/doop.c
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2015-09-21 14:49:22 +0100
committerDavid Mitchell <davem@iabyn.com>2015-10-02 11:29:35 +0100
commit052a7c766b9640ee847979cb9d2351a63e23a378 (patch)
tree1a796b916aa4702854196a5c6ef9767b4d6b98e8 /doop.c
parent6768377c79109b7124f0c8a4e3677982689d9f49 (diff)
downloadperl-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 'doop.c')
-rw-r--r--doop.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/doop.c b/doop.c
index 19fe3105d5..5dbd8a29cc 100644
--- a/doop.c
+++ b/doop.c
@@ -1220,6 +1220,7 @@ Perl_do_kv(pTHX)
dSP;
HV * const keys = MUTABLE_HV(POPs);
HE *entry;
+ SSize_t extend_size;
const I32 gimme = GIMME_V;
const I32 dokv = (PL_op->op_type == OP_RV2HV || PL_op->op_type == OP_PADHV);
/* op_type is OP_RKEYS/OP_RVALUES if pp_rkeys delegated to here */
@@ -1255,7 +1256,10 @@ Perl_do_kv(pTHX)
RETURN;
}
- EXTEND(SP, HvUSEDKEYS(keys) * (dokeys + dovalues));
+ /* 2*HvUSEDKEYS() should never be big enough to truncate or wrap */
+ assert(HvUSEDKEYS(keys) <= (SSize_t_MAX >> 1));
+ extend_size = (SSize_t)HvUSEDKEYS(keys) * (dokeys + dovalues);
+ EXTEND(SP, extend_size);
while ((entry = hv_iternext(keys))) {
if (dokeys) {