This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #123893] Fix hang with "@{"
[perl5.git] / av.c
diff --git a/av.c b/av.c
index 49fef00..53690d5 100644 (file)
--- a/av.c
+++ b/av.c
@@ -130,14 +130,23 @@ Perl_av_extend_guts(pTHX_ AV *av, SSize_t key, SSize_t *maxp, SV ***allocp,
                if (key <= newmax) 
                    goto resized;
 #endif 
-               newmax = key + *maxp / 5;
+                /* overflow-safe version of newmax = key + *maxp/5 */
+               newmax = *maxp / 5;
+                newmax = (key > SSize_t_MAX - newmax)
+                            ? SSize_t_MAX : key + newmax;
              resize:
                {
 #ifdef PERL_MALLOC_WRAP /* Duplicated in pp_hot.c */
                    static const char oom_array_extend[] =
                        "Out of memory during array extend";
 #endif
-                   MEM_WRAP_CHECK_1(newmax+1, SV*, oom_array_extend);
+                    /* it should really be newmax+1 here, but if newmax
+                     * happens to equal SSize_t_MAX, then newmax+1 is
+                     * undefined. This means technically we croak one
+                     * index lower than we should in theory; in practice
+                     * its unlikely the system has SSize_t_MAX/sizeof(SV*)
+                     * bytes to spare! */
+                   MEM_WRAP_CHECK_1(newmax, SV*, oom_array_extend);
                }
 #ifdef STRESS_REALLOC
                {
@@ -167,7 +176,8 @@ Perl_av_extend_guts(pTHX_ AV *av, SSize_t key, SSize_t *maxp, SV ***allocp,
                    static const char oom_array_extend[] =
                        "Out of memory during array extend";
 #endif
-                   MEM_WRAP_CHECK_1(newmax+1, SV*, oom_array_extend);
+                    /* see comment above about newmax+1*/
+                   MEM_WRAP_CHECK_1(newmax, SV*, oom_array_extend);
                }
                Newx(*allocp, newmax+1, SV*);
                ary = *allocp + 1;
@@ -748,10 +758,6 @@ The Perl equivalent for this is C<$#myarray>.
 
 (A slightly shorter form is C<av_tindex>.)
 
-=for apidoc av_tindex
-
-Same as L</av_top_index>.
-
 =for apidoc av_len
 
 Same as L</av_top_index>.  Note that, unlike what the name implies, it returns
@@ -776,7 +782,7 @@ Perl_av_len(pTHX_ AV *av)
 Set the highest index in the array to the given number, equivalent to
 Perl's C<$#array = $fill;>.
 
-The number of elements in the an array will be C<fill + 1> after
+The number of elements in the array will be C<fill + 1> after
 av_fill() returns.  If the array was previously shorter, then the
 additional elements appended are set to NULL.  If the array
 was longer, then the excess elements are freed.  C<av_fill(av, -1)> is