/* This checks for overflow of the array dimensions */
     nitems = ArrayGetNItems(ndim, dim);
 +   ArrayCheckBounds(ndim, dim, lBound);
 +
     /* Empty array? */
     if (nitems == 0)
         PG_RETURN_ARRAYTYPE_P(construct_empty_array(element_type));
      {
         dim[i] = pq_getmsgint(buf, 4);
         lBound[i] = pq_getmsgint(buf, 4);
 -
 -       /*
 -        * Check overflow of upper bound. (ArrayGetNItems() below checks that
 -        * dim[i] >= 0)
 -        */
 -       if (dim[i] != 0)
 -       {
 -           int         ub = lBound[i] + dim[i] - 1;
 -
 -           if (lBound[i] > ub)
 -               ereport(ERROR,
 -                       (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 -                        errmsg("integer out of range")));
 -       }
     }
  
     /* This checks for overflow of array dimensions */
     nitems = ArrayGetNItems(ndim, dim);
 +   ArrayCheckBounds(ndim, dim, lBound);
  
     /*
      * We arrange to look up info about element type, including its receive
                      (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
                      errmsg("wrong number of array subscripts")));
  
 -       if (indx[0] < 0 || indx[0] * elmlen >= arraytyplen)
 +       if (indx[0] < 0 || indx[0] >= arraytyplen / elmlen)
             ereport(ERROR,
                     (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
                      errmsg("array subscript out of range")));
          }
     }
  
 +   /* This checks for overflow of the array dimensions */
 +   newnitems = ArrayGetNItems(ndim, dim);
 +   ArrayCheckBounds(ndim, dim, lb);
 +
     /*
      * Compute sizes of items and areas to copy
      */
 -   newnitems = ArrayGetNItems(ndim, dim);
     if (newhasnulls)
         overheadlen = ARR_OVERHEAD_WITHNULLS(ndim, newnitems);
     else
          }
     }
  
 +   /* Check for overflow of the array dimensions */
 +   if (dimschanged)
 +   {
 +       (void) ArrayGetNItems(ndim, dim);
 +       ArrayCheckBounds(ndim, dim, lb);
 +   }
 +
     /* Now we can calculate linear offset of target item in array */
     offset = ArrayGetOffset(nSubscripts, dim, lb, indx);
  
   
     /* Do this mainly to check for overflow */
     nitems = ArrayGetNItems(ndim, dim);
 +   ArrayCheckBounds(ndim, dim, lb);
  
     /*
      * Make sure source array has enough entries.  Note we ignore the shape of
                   errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
                         ndims, MAXDIM)));
  
 +   /* This checks for overflow of the array dimensions */
     nelems = ArrayGetNItems(ndims, dims);
 +   ArrayCheckBounds(ndims, dims, lbs);
  
     /* if ndims <= 0 or any dims[i] == 0, return empty array */
     if (nelems <= 0)
          int         dataoffset,
                     nbytes;
  
 +       /* Check for overflow of the array dimensions */
 +       (void) ArrayGetNItems(astate->ndims, astate->dims);
 +       ArrayCheckBounds(astate->ndims, astate->dims, astate->lbs);
 +
         /* Compute required space */
         nbytes = astate->nbytes;
         if (astate->nullbitmap != NULL)
          lbsv = deflbs;
     }
  
 +   /* This checks for overflow of the array dimensions */
     nitems = ArrayGetNItems(ndims, dimv);
 +   ArrayCheckBounds(ndims, dimv, lbsv);
  
     /* fast track for empty array */
     if (nitems <= 0)
          #include "postgres.h"
  
  #include "catalog/pg_type.h"
 +#include "common/int.h"
  #include "utils/array.h"
  #include "utils/builtins.h"
  #include "utils/memutils.h"
      return (int) ret;
  }
  
 +/*
 + * Verify sanity of proposed lower-bound values for an array
 + *
 + * The lower-bound values must not be so large as to cause overflow when
 + * calculating subscripts, e.g. lower bound 2147483640 with length 10
 + * must be disallowed.  We actually insist that dims[i] + lb[i] be
 + * computable without overflow, meaning that an array with last subscript
 + * equal to INT_MAX will be disallowed.
 + *
 + * It is assumed that the caller already called ArrayGetNItems, so that
 + * overflowed (negative) dims[] values have been eliminated.
 + */
 +void
 +ArrayCheckBounds(int ndim, const int *dims, const int *lb)
 +{
 +   int         i;
 +
 +   for (i = 0; i < ndim; i++)
 +   {
 +       /* PG_USED_FOR_ASSERTS_ONLY prevents variable-isn't-read warnings */
 +       int32       sum PG_USED_FOR_ASSERTS_ONLY;
 +
 +       if (pg_add_s32_overflow(dims[i], lb[i], &sum))
 +           ereport(ERROR,
 +                   (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 +                    errmsg("array lower bound is too large: %d",
 +                           lb[i])));
 +   }
 +}
 +
  /*
   * Compute ranges (sub-array dimensions) for an array slice
   *
          extern int ArrayGetOffset(int n, const int *dim, const int *lb, const int *indx);
  extern int ArrayGetOffset0(int n, const int *tup, const int *scale);
  extern int ArrayGetNItems(int ndim, const int *dims);
 +extern void ArrayCheckBounds(int ndim, const int *dims, const int *lb);
  extern void mda_get_range(int n, int *span, const int *st, const int *endp);
  extern void mda_get_prod(int n, const int *range, int *prod);
  extern void mda_get_offset_values(int n, int *dist, const int *prod, const int *span);