In perl.git, the branch blead has been updated

<http://perl5.git.perl.org/perl.git/commitdiff/b3b27d017bd3d61f6cbc3eaf8465b8d98d86a024?hp=b9a07097bdb32335cd4963591c6f2d29bc6302a8>

- Log -----------------------------------------------------------------
commit b3b27d017bd3d61f6cbc3eaf8465b8d98d86a024
Author: David Mitchell <[email protected]>
Date:   Wed Mar 11 12:25:58 2015 +0000

    repeat op: avoid integer overflows
    
    For the list variant of the x operator, the overflow detection code
    doesn't always work, resulting in the stack not being extended enough.
    
    There are two places where an overflow could occur: calculating how
    many stack items to extend by (items * count), and passing to repeatcpy()
    how many bytes to copy 'items' SV pointers (items * sizeof(const SV *)).
    
    The overflow detection was generally a mess; checking for overflow
    using a value (max) that may have already overflown; checking whether
    'max' had overflown incorrectly, and not checking (items * sizeof(const SV
    *) at all (perhaps hoping that the other checks would be a superset of
    this).
    
    Also, some of the vars were still I32s; promote to 64-bit capable types.
    
    Finally, the signature of Perl_repeatcpy() still has an I32 len;
    that really should be changed to IV at some point; but for now I've just
    ensured that the callers (list 'x' and scalar 'x') don't wrap.
    I haven't put in a check for the only other core caller of repeatcpy(),
    S_study_chunk(), since that would only become an issue compiling a pattern
    with a fixed or floating substr within it of length > 2**31.
-----------------------------------------------------------------------

Summary of changes:
 pp.c | 35 ++++++++++++++++++++---------------
 1 file changed, 20 insertions(+), 15 deletions(-)

diff --git a/pp.c b/pp.c
index f795725..ec0f9d3 100644
--- a/pp.c
+++ b/pp.c
@@ -1717,17 +1717,19 @@ PP(pp_repeat)
 
     if (GIMME_V == G_ARRAY && PL_op->op_private & OPpREPEAT_DOLIST) {
        dMARK;
-       static const char* const oom_list_extend = "Out of memory during list 
extend";
-       const I32 items = SP - MARK;
-       const I32 max = items * count;
+       const Size_t items = SP - MARK;
        const U8 mod = PL_op->op_flags & OPf_MOD;
 
-       MEM_WRAP_CHECK_1(max, SV*, oom_list_extend);
-       /* Did the max computation overflow? */
-       if (items > 0 && max > 0 && (max < items || max < count))
-          Perl_croak(aTHX_ "%s", oom_list_extend);
-       MEXTEND(MARK, max);
        if (count > 1) {
+           Size_t max;
+
+            if (  items > MEM_SIZE_MAX / (UV)count   /* max would overflow */
+               || items > (U32)I32_MAX / sizeof(SV *) /* repeatcpy would 
overflow */
+            )
+               Perl_croak(aTHX_ "%s","Out of memory during list extend");
+            max = items * count;
+            MEXTEND(MARK, max);
+
            while (SP > MARK) {
                 if (*SP) {
                    if (mod && SvPADTMP(*SP)) {
@@ -1749,8 +1751,6 @@ PP(pp_repeat)
        SV * const tmpstr = POPs;
        STRLEN len;
        bool isutf;
-       static const char* const oom_string_extend =
-         "Out of memory during string extend";
 
        if (TARG != tmpstr)
            sv_setsv_nomg(TARG, tmpstr);
@@ -1760,11 +1760,16 @@ PP(pp_repeat)
            if (count < 1)
                SvCUR_set(TARG, 0);
            else {
-               const STRLEN max = (UV)count * len;
-               if (len > MEM_SIZE_MAX / count)
-                    Perl_croak(aTHX_ "%s", oom_string_extend);
-               MEM_WRAP_CHECK_1(max, char, oom_string_extend);
-               SvGROW(TARG, max + 1);
+               STRLEN max;
+
+               if (   len > (MEM_SIZE_MAX-1) / (UV)count /* max would overflow 
*/
+                   || len > (U32)I32_MAX  /* repeatcpy would overflow */
+                )
+                    Perl_croak(aTHX_ "%s",
+                                        "Out of memory during string extend");
+               max = (UV)count * len + 1;
+               SvGROW(TARG, max);
+
                repeatcpy(SvPVX(TARG) + len, SvPVX(TARG), len, count - 1);
                SvCUR_set(TARG, SvCUR(TARG) * count);
            }

--
Perl5 Master Repository

Reply via email to