In perl.git, the branch blead has been updated

<http://perl5.git.perl.org/perl.git/commitdiff/95d8e32b92e4e78f0c172dd82ff70a8a96bb1451?hp=c61597183215b0dad8f01e5b9d60419ce3768b41>

- Log -----------------------------------------------------------------
commit 95d8e32b92e4e78f0c172dd82ff70a8a96bb1451
Merge: c615971832 a7dd840b16
Author: David Mitchell <[email protected]>
Date:   Wed Mar 15 09:25:51 2017 +0000

    [MERGE] fixes and tests for Renew (RT #130841)

commit a7dd840b16566dcdb761159060e3f05d9ed57073
Author: David Mitchell <[email protected]>
Date:   Tue Mar 7 15:22:49 2017 +0000

    add range.t test for RT #130841

M       t/op/range.t

commit 00195859c65eccf9425faf45db543a12c7ad3874
Author: Hugo van der Sanden <[email protected]>
Date:   Tue Feb 28 11:23:09 2017 +0000

    update size after Renew
    
    RT #130841
    
    In general code, change this idiom:
    
        PL_foo_max += size;
        Renew(PL_foo, PL_foo_max, foo_t);
    
    to
        Renew(PL_foo, PL_foo_max + size, foo_t);
        PL_foo_max += size;
    
    so that if Renew dies, PL_foo_max won't be left hanging.

M       perlio.c
M       pp_hot.c
M       pp_sort.c
M       regcomp.c
M       scope.c
M       util.c

commit acfc2cc32784cce84bd781bc3822b14406b94db2
Author: Hugo van der Sanden <[email protected]>
Date:   Tue Feb 28 11:21:55 2017 +0000

    reentr: update size after Renew
    
    RT #130841
    
    Setting it before Renew can cause problems if the Renew fails.
    
    Required 'make regen'.

M       reentr.c
M       regen/reentr.pl

commit 35a27ac0799b5ce44b9a5af182c93c3d5c266026
Author: Hugo van der Sanden <[email protected]>
Date:   Tue Feb 28 11:21:09 2017 +0000

    WIN32: update size after Renew
    
    RT #130841
    
    Setting it before Renew can cause problems if the Renew fails.

M       win32/win32.c
M       win32/wince.c
-----------------------------------------------------------------------

Summary of changes:
 perlio.c        |  7 ++++---
 pp_hot.c        |  2 +-
 pp_sort.c       |  2 +-
 reentr.c        | 37 +++++++++++++++++++------------------
 regcomp.c       | 10 ++++++----
 regen/reentr.pl | 37 +++++++++++++++++++------------------
 scope.c         | 29 +++++++++++++++++------------
 t/op/range.t    | 33 +++++++++++++++++++++++++++++++--
 util.c          | 18 +++++++++++-------
 win32/win32.c   |  2 +-
 win32/wince.c   |  2 +-
 11 files changed, 111 insertions(+), 68 deletions(-)

diff --git a/perlio.c b/perlio.c
index 3e936a26d0..e9d3700cfe 100644
--- a/perlio.c
+++ b/perlio.c
@@ -547,11 +547,12 @@ PerlIO_list_push(pTHX_ PerlIO_list_t *list, PerlIO_funcs 
*funcs, SV *arg)
     PERL_UNUSED_CONTEXT;
 
     if (list->cur >= list->len) {
-       list->len += 8;
+        const IV new_len = list->len + 8;
        if (list->array)
-           Renew(list->array, list->len, PerlIO_pair_t);
+           Renew(list->array, new_len, PerlIO_pair_t);
        else
-           Newx(list->array, list->len, PerlIO_pair_t);
+           Newx(list->array, new_len, PerlIO_pair_t);
+       list->len = new_len;
     }
     p = &(list->array[list->cur++]);
     p->funcs = funcs;
diff --git a/pp_hot.c b/pp_hot.c
index 58bbe2f1e9..4f0d094ce6 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -4134,8 +4134,8 @@ PP(pp_entersub)
             items = SP - MARK;
            if (UNLIKELY(items - 1 > AvMAX(av))) {
                 SV **ary = AvALLOC(av);
-                AvMAX(av) = items - 1;
                 Renew(ary, items, SV*);
+                AvMAX(av) = items - 1;
                 AvALLOC(av) = ary;
                 AvARRAY(av) = ary;
             }
diff --git a/pp_sort.c b/pp_sort.c
index 21e4574c1f..a54768a022 100644
--- a/pp_sort.c
+++ b/pp_sort.c
@@ -1831,8 +1831,8 @@ S_sortcv_stacked(pTHX_ SV *const a, SV *const b)
            AvARRAY(av) = ary;
        }
        if (AvMAX(av) < 1) {
-           AvMAX(av) = 1;
            Renew(ary,2,SV*);
+           AvMAX(av) = 1;
            AvARRAY(av) = ary;
            AvALLOC(av) = ary;
        }
diff --git a/reentr.c b/reentr.c
index c464acc834..70b971b5a4 100644
--- a/reentr.c
+++ b/reentr.c
@@ -33,6 +33,13 @@
 #include "perl.h"
 #include "reentr.h"
 
+#define RenewDouble(data_pointer, size_pointer, type) \
+    STMT_START { \
+       const size_t size = *(size_pointer) * 2; \
+       Renew((data_pointer), (size), type); \
+       *(size_pointer) = size; \
+    } STMT_END
+
 void
 Perl_reentrant_size(pTHX) {
        PERL_UNUSED_CONTEXT;
@@ -326,9 +333,8 @@ Perl_reentrant_retry(const char *f, ...)
                PERL_REENTRANT_MAXSIZE / 2)
 #endif
            {
-               PL_reentrant_buffer->_hostent_size *= 2;
-               Renew(PL_reentrant_buffer->_hostent_buffer,
-                     PL_reentrant_buffer->_hostent_size, char);
+               RenewDouble(PL_reentrant_buffer->_hostent_buffer,
+                       &PL_reentrant_buffer->_hostent_size, char);
                switch (PL_op->op_type) {
                case OP_GHBYADDR:
                    p0    = va_arg(ap, void *);
@@ -359,9 +365,8 @@ Perl_reentrant_retry(const char *f, ...)
 #endif
            {
                Gid_t gid;
-               PL_reentrant_buffer->_grent_size *= 2;
-               Renew(PL_reentrant_buffer->_grent_buffer,
-                     PL_reentrant_buffer->_grent_size, char);
+               RenewDouble(PL_reentrant_buffer->_grent_buffer,
+                     &PL_reentrant_buffer->_grent_size, char);
                switch (PL_op->op_type) {
                case OP_GGRNAM:
                    p0 = va_arg(ap, void *);
@@ -394,9 +399,8 @@ Perl_reentrant_retry(const char *f, ...)
 #endif
            {
                Netdb_net_t net;
-               PL_reentrant_buffer->_netent_size *= 2;
-               Renew(PL_reentrant_buffer->_netent_buffer,
-                     PL_reentrant_buffer->_netent_size, char);
+               RenewDouble(PL_reentrant_buffer->_netent_buffer,
+                     &PL_reentrant_buffer->_netent_size, char);
                switch (PL_op->op_type) {
                case OP_GNBYADDR:
                    net = va_arg(ap, Netdb_net_t);
@@ -426,9 +430,8 @@ Perl_reentrant_retry(const char *f, ...)
 #endif
            {
                Uid_t uid;
-               PL_reentrant_buffer->_pwent_size *= 2;
-               Renew(PL_reentrant_buffer->_pwent_buffer,
-                     PL_reentrant_buffer->_pwent_size, char);
+               RenewDouble(PL_reentrant_buffer->_pwent_buffer,
+                     &PL_reentrant_buffer->_pwent_size, char);
                switch (PL_op->op_type) {
                case OP_GPWNAM:
                    p0 = va_arg(ap, void *);
@@ -462,9 +465,8 @@ Perl_reentrant_retry(const char *f, ...)
                PERL_REENTRANT_MAXSIZE / 2)
 #endif
            {
-               PL_reentrant_buffer->_protoent_size *= 2;
-               Renew(PL_reentrant_buffer->_protoent_buffer,
-                     PL_reentrant_buffer->_protoent_size, char);
+               RenewDouble(PL_reentrant_buffer->_protoent_buffer,
+                     &PL_reentrant_buffer->_protoent_size, char);
                switch (PL_op->op_type) {
                case OP_GPBYNAME:
                    p0 = va_arg(ap, void *);
@@ -492,9 +494,8 @@ Perl_reentrant_retry(const char *f, ...)
                PERL_REENTRANT_MAXSIZE / 2)
 #endif
            {
-               PL_reentrant_buffer->_servent_size *= 2;
-               Renew(PL_reentrant_buffer->_servent_buffer,
-                     PL_reentrant_buffer->_servent_size, char);
+               RenewDouble(PL_reentrant_buffer->_servent_buffer,
+                     &PL_reentrant_buffer->_servent_size, char);
                switch (PL_op->op_type) {
                case OP_GSBYNAME:
                    p0 = va_arg(ap, void *);
diff --git a/regcomp.c b/regcomp.c
index 0a80cedec5..810c4573d1 100644
--- a/regcomp.c
+++ b/regcomp.c
@@ -2355,8 +2355,9 @@ is the recommended Unicode-aware way of saying
 
 #define TRIE_LIST_PUSH(state,fid,ns) STMT_START {               \
     if ( TRIE_LIST_CUR( state ) >=TRIE_LIST_LEN( state ) ) {    \
-       U32 ging = TRIE_LIST_LEN( state ) *= 2;                 \
+       U32 ging = TRIE_LIST_LEN( state ) * 2;                  \
        Renew( trie->states[ state ].trans.list, ging, reg_trie_trans_le ); \
+        TRIE_LIST_LEN( state ) = ging;                          \
     }                                                           \
     TRIE_LIST_ITEM( state, TRIE_LIST_CUR( state ) ).forid = fid;     \
     TRIE_LIST_ITEM( state, TRIE_LIST_CUR( state ) ).newstate = ns;   \
@@ -6416,10 +6417,11 @@ S_concat_pat(pTHX_ RExC_state_t * const pRExC_state,
                  * different closure than last time */
                 *recompile_p = 1;
                 if (pRExC_state->code_blocks) {
-                    pRExC_state->code_blocks->count += ri->code_blocks->count;
+                    int new_count = pRExC_state->code_blocks->count
+                            + ri->code_blocks->count;
                     Renew(pRExC_state->code_blocks->cb,
-                            pRExC_state->code_blocks->count,
-                            struct reg_code_block);
+                            new_count, struct reg_code_block);
+                    pRExC_state->code_blocks->count = new_count;
                 }
                 else
                     pRExC_state->code_blocks = S_alloc_code_blocks(aTHX_
diff --git a/regen/reentr.pl b/regen/reentr.pl
index 802b8db90d..f8f78a5152 100644
--- a/regen/reentr.pl
+++ b/regen/reentr.pl
@@ -773,6 +773,13 @@ print $c <<"EOF";
 #include "perl.h"
 #include "reentr.h"
 
+#define RenewDouble(data_pointer, size_pointer, type) \\
+    STMT_START { \\
+       const size_t size = *(size_pointer) * 2; \\
+       Renew((data_pointer), (size), type); \\
+       *(size_pointer) = size; \\
+    } STMT_END
+
 void
 Perl_reentrant_size(pTHX) {
        PERL_UNUSED_CONTEXT;
@@ -840,9 +847,8 @@ Perl_reentrant_retry(const char *f, ...)
                PERL_REENTRANT_MAXSIZE / 2)
 #endif
            {
-               PL_reentrant_buffer->_hostent_size *= 2;
-               Renew(PL_reentrant_buffer->_hostent_buffer,
-                     PL_reentrant_buffer->_hostent_size, char);
+               RenewDouble(PL_reentrant_buffer->_hostent_buffer,
+                       &PL_reentrant_buffer->_hostent_size, char);
                switch (PL_op->op_type) {
                case OP_GHBYADDR:
                    p0    = va_arg(ap, void *);
@@ -873,9 +879,8 @@ Perl_reentrant_retry(const char *f, ...)
 #endif
            {
                Gid_t gid;
-               PL_reentrant_buffer->_grent_size *= 2;
-               Renew(PL_reentrant_buffer->_grent_buffer,
-                     PL_reentrant_buffer->_grent_size, char);
+               RenewDouble(PL_reentrant_buffer->_grent_buffer,
+                     &PL_reentrant_buffer->_grent_size, char);
                switch (PL_op->op_type) {
                case OP_GGRNAM:
                    p0 = va_arg(ap, void *);
@@ -908,9 +913,8 @@ Perl_reentrant_retry(const char *f, ...)
 #endif
            {
                Netdb_net_t net;
-               PL_reentrant_buffer->_netent_size *= 2;
-               Renew(PL_reentrant_buffer->_netent_buffer,
-                     PL_reentrant_buffer->_netent_size, char);
+               RenewDouble(PL_reentrant_buffer->_netent_buffer,
+                     &PL_reentrant_buffer->_netent_size, char);
                switch (PL_op->op_type) {
                case OP_GNBYADDR:
                    net = va_arg(ap, Netdb_net_t);
@@ -940,9 +944,8 @@ Perl_reentrant_retry(const char *f, ...)
 #endif
            {
                Uid_t uid;
-               PL_reentrant_buffer->_pwent_size *= 2;
-               Renew(PL_reentrant_buffer->_pwent_buffer,
-                     PL_reentrant_buffer->_pwent_size, char);
+               RenewDouble(PL_reentrant_buffer->_pwent_buffer,
+                     &PL_reentrant_buffer->_pwent_size, char);
                switch (PL_op->op_type) {
                case OP_GPWNAM:
                    p0 = va_arg(ap, void *);
@@ -976,9 +979,8 @@ Perl_reentrant_retry(const char *f, ...)
                PERL_REENTRANT_MAXSIZE / 2)
 #endif
            {
-               PL_reentrant_buffer->_protoent_size *= 2;
-               Renew(PL_reentrant_buffer->_protoent_buffer,
-                     PL_reentrant_buffer->_protoent_size, char);
+               RenewDouble(PL_reentrant_buffer->_protoent_buffer,
+                     &PL_reentrant_buffer->_protoent_size, char);
                switch (PL_op->op_type) {
                case OP_GPBYNAME:
                    p0 = va_arg(ap, void *);
@@ -1006,9 +1008,8 @@ Perl_reentrant_retry(const char *f, ...)
                PERL_REENTRANT_MAXSIZE / 2)
 #endif
            {
-               PL_reentrant_buffer->_servent_size *= 2;
-               Renew(PL_reentrant_buffer->_servent_buffer,
-                     PL_reentrant_buffer->_servent_size, char);
+               RenewDouble(PL_reentrant_buffer->_servent_buffer,
+                     &PL_reentrant_buffer->_servent_size, char);
                switch (PL_op->op_type) {
                case OP_GSBYNAME:
                    p0 = va_arg(ap, void *);
diff --git a/scope.c b/scope.c
index 4b302e7665..c51a125dfa 100644
--- a/scope.c
+++ b/scope.c
@@ -90,11 +90,12 @@ I32
 Perl_cxinc(pTHX)
 {
     const IV old_max = cxstack_max;
-    cxstack_max = GROW(cxstack_max);
-    Renew(cxstack, cxstack_max + 1, PERL_CONTEXT);
+    const IV new_max = GROW(cxstack_max);
+    Renew(cxstack, new_max + 1, PERL_CONTEXT);
+    cxstack_max = new_max;
     /* Without any kind of initialising deep enough recursion
      * will end up reading uninitialised PERL_CONTEXTs. */
-    PoisonNew(cxstack + old_max + 1, cxstack_max - old_max, PERL_CONTEXT);
+    PoisonNew(cxstack + old_max + 1, new_max - old_max, PERL_CONTEXT);
     return cxstack_ix + 1;
 }
 
@@ -102,11 +103,12 @@ void
 Perl_push_scope(pTHX)
 {
     if (UNLIKELY(PL_scopestack_ix == PL_scopestack_max)) {
-       PL_scopestack_max = GROW(PL_scopestack_max);
-       Renew(PL_scopestack, PL_scopestack_max, I32);
+        const IV new_max = GROW(PL_scopestack_max);
+       Renew(PL_scopestack, new_max, I32);
 #ifdef DEBUGGING
-       Renew(PL_scopestack_name, PL_scopestack_max, const char*);
+       Renew(PL_scopestack_name, new_max, const char*);
 #endif
+       PL_scopestack_max = new_max;
     }
 #ifdef DEBUGGING
     PL_scopestack_name[PL_scopestack_ix] = "unknown";
@@ -140,23 +142,26 @@ Perl_markstack_grow(pTHX)
 void
 Perl_savestack_grow(pTHX)
 {
+    IV new_max;
 #ifdef STRESS_REALLOC
-    PL_savestack_max += SS_MAXPUSH;
+    new_max = PL_savestack_max + SS_MAXPUSH;
 #else
-    PL_savestack_max = GROW(PL_savestack_max);
+    new_max = GROW(PL_savestack_max);
 #endif
     /* Note that we allocate SS_MAXPUSH slots higher than ss_max
      * so that SS_ADD_END(), SSGROW() etc can do a simper check */
-    Renew(PL_savestack, PL_savestack_max + SS_MAXPUSH, ANY);
+    Renew(PL_savestack, new_max + SS_MAXPUSH, ANY);
+    PL_savestack_max = new_max;
 }
 
 void
 Perl_savestack_grow_cnt(pTHX_ I32 need)
 {
-    PL_savestack_max = PL_savestack_ix + need;
+    const IV new_max = PL_savestack_ix + need;
     /* Note that we allocate SS_MAXPUSH slots higher than ss_max
      * so that SS_ADD_END(), SSGROW() etc can do a simper check */
-    Renew(PL_savestack, PL_savestack_max + SS_MAXPUSH, ANY);
+    Renew(PL_savestack, new_max + SS_MAXPUSH, ANY);
+    PL_savestack_max = new_max;
 }
 
 #undef GROW
@@ -186,8 +191,8 @@ Perl_tmps_grow_p(pTHX_ SSize_t ix)
     if (ix - PL_tmps_max < 128)
        extend_to += (PL_tmps_max < 512) ? 128 : 512;
 #endif
+    Renew(PL_tmps_stack, extend_to + 1, SV*);
     PL_tmps_max = extend_to + 1;
-    Renew(PL_tmps_stack, PL_tmps_max, SV*);
     return ix;
 }
 
diff --git a/t/op/range.t b/t/op/range.t
index e58a39c8e8..02a38e0497 100644
--- a/t/op/range.t
+++ b/t/op/range.t
@@ -9,7 +9,7 @@ BEGIN {
 
 use Config;
 
-plan (145);
+plan (146);
 
 is(join(':',1..5), '1:2:3:4:5');
 
@@ -417,4 +417,33 @@ is( ( join ' ', map { join '', map ++$_, 'a'..'d'      } 
1..2 ), 'bcde bcde',
 $s = ''; for (1..2) { for ('a'..'d') { $s .= ++$_ } $s.=' ' if $_==1; }
 is( $s, 'bcde bcde','modifiable alpha counting loop counter' );
 
-# EOF
+# RT #130841
+# generating an extreme range triggered a croak, which if caught,
+# left the temps stack small but with a very large PL_tmps_max
+
+fresh_perl_like(<<'EOF', qr/\Aok 1 ok 2\Z/, {}, "RT #130841");
+my $max_iv = (~0 >> 1);
+eval {
+    my @range = 1..($max_iv - 1);
+};
+if ($@ =~ /panic: memory wrap|Out of memory/) {
+    print "ok 1";
+}
+else {
+    print "unexpected err status: [$@]";
+}
+
+# create and push lots of temps
+my $max = 10_000;
+my @ints = map $_+1, 0..($max-1);
+my $sum = 0;
+$sum += $_ for @ints;
+my $exp = $max*($max+1)/2;
+if ($sum == $exp) {
+    print " ok 2";
+}
+else {
+    print " unexpected sum: [$sum]; expected: [$exp]";
+}
+EOF
+
diff --git a/util.c b/util.c
index bd568bc22a..b324af43ed 100644
--- a/util.c
+++ b/util.c
@@ -5352,9 +5352,11 @@ Perl_my_cxt_init(pTHX_ int *index, size_t size)
     /* make sure the array is big enough */
     if (PL_my_cxt_size <= *index) {
        if (PL_my_cxt_size) {
-           while (PL_my_cxt_size <= *index)
-               PL_my_cxt_size *= 2;
-           Renew(PL_my_cxt_list, PL_my_cxt_size, void *);
+            IV new_size = PL_my_cxt_size;
+           while (new_size <= *index)
+               new_size *= 2;
+           Renew(PL_my_cxt_list, new_size, void *);
+            PL_my_cxt_size = new_size;
        }
        else {
            PL_my_cxt_size = 16;
@@ -5415,10 +5417,12 @@ Perl_my_cxt_init(pTHX_ const char *my_cxt_key, size_t 
size)
        int old_size = PL_my_cxt_size;
        int i;
        if (PL_my_cxt_size) {
-           while (PL_my_cxt_size <= index)
-               PL_my_cxt_size *= 2;
-           Renew(PL_my_cxt_list, PL_my_cxt_size, void *);
-           Renew(PL_my_cxt_keys, PL_my_cxt_size, const char *);
+            IV new_size = PL_my_cxt_size;
+           while (new_size <= index)
+               new_size *= 2;
+           Renew(PL_my_cxt_list, new_size, void *);
+           Renew(PL_my_cxt_keys, new_size, const char *);
+            PL_my_cxt_size = new_size;
        }
        else {
            PL_my_cxt_size = 16;
diff --git a/win32/win32.c b/win32/win32.c
index 39819212d2..2e82c53462 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -968,8 +968,8 @@ win32_readdir(DIR *dirp)
                 * new name and its null terminator */
                while (newsize > dirp->size) {
                    long curpos = dirp->curr - dirp->start;
+                   Renew(dirp->start, dirp->size * 2, char);
                    dirp->size *= 2;
-                   Renew(dirp->start, dirp->size, char);
                    dirp->curr = dirp->start + curpos;
                }
                strcpy(dirp->start + endpos, buffer);
diff --git a/win32/wince.c b/win32/wince.c
index 56a23b5e98..045853779a 100644
--- a/win32/wince.c
+++ b/win32/wince.c
@@ -765,8 +765,8 @@ win32_readdir(DIR *dirp)
                 * new name and its null terminator */
                while (newsize > dirp->size) {
                    long curpos = dirp->curr - dirp->start;
+                   Renew(dirp->start, dirp->size * 2, char);
                    dirp->size *= 2;
-                   Renew(dirp->start, dirp->size, char);
                    dirp->curr = dirp->start + curpos;
                }
                strcpy(dirp->start + endpos, ptr);

--
Perl5 Master Repository

Reply via email to