*** braces.c		2012-05-29 13:02:46.138008592 +1000
--- bash-4.2-patched/braces.c	2012-06-05 13:45:29.555694933 +1000
***************
*** 31,36 ****
--- 31,37 ----
  #  include <unistd.h>
  #endif
  
+ #include <errno.h>
  #include "bashansi.h"
  
  #if defined (SHELL)
***************
*** 63,69 ****
  static int brace_gobbler __P((char *, size_t, int *, int));
  static char **expand_amble __P((char *, size_t, int));
  static char **expand_seqterm __P((char *, size_t));
! static char **mkseq __P((intmax_t, intmax_t, int, int, int));
  static char **array_concat __P((char **, char **));
  #else
  static int brace_gobbler ();
--- 64,70 ----
  static int brace_gobbler __P((char *, size_t, int *, int));
  static char **expand_amble __P((char *, size_t, int));
  static char **expand_seqterm __P((char *, size_t));
! static char **mkseq __P((intmax_t, intmax_t, intmax_t, int, int));
  static char **array_concat __P((char **, char **));
  #else
  static int brace_gobbler ();
***************
*** 305,330 ****
  #define ST_CHAR	2
  #define ST_ZINT	3
  
  static char **
  mkseq (start, end, incr, type, width)
!      intmax_t start, end;
!      int incr, type, width;
  {
    intmax_t n;
    int i;
    char **result, *t;
  
-   i = abs (end - start) + 1;
-   result = strvec_create (i + 1);
- 
    if (incr == 0)
      incr = 1;
    
    if (start > end && incr > 0)
      incr = -incr;
    else if (start < end && incr < 0)
      incr = -incr;
! 
    /* Make sure we go through the loop at least once, so {3..3} prints `3' */
    i = 0;
    n = start;
--- 306,377 ----
  #define ST_CHAR	2
  #define ST_ZINT	3
  
+ /* Returns true if lhs + rhs would under/overflow outside of [minval, maxval].*/
+ static int
+ addwilloverflow(lhs, rhs, minval, maxval)
+       intmax_t lhs, rhs, minval, maxval;
+ {
+   return
+     (((lhs > 0) && (rhs > (maxval - lhs)))
+     ||
+     ((lhs < 0) && (rhs < (minval - lhs))));
+ }
+ 
+ /* Returns true if lhs - rhs would under/overflow outside of [minval, maxval].*/
+ static int
+ subtractwilloverflow(lhs, rhs, minval, maxval)
+       intmax_t lhs, rhs, minval, maxval;
+ {
+   return
+     (((rhs > 0) && (lhs < (minval + rhs)))
+     ||
+     ((rhs < 0) && (lhs > (maxval + rhs))));
+ }
+ 
+ /* Will return NULL on error. */
  static char **
  mkseq (start, end, incr, type, width)
!      intmax_t start, end, incr;
!      int type, width;
  {
    intmax_t n;
    int i;
    char **result, *t;
  
    if (incr == 0)
      incr = 1;
    
    if (start > end && incr > 0)
+   {
      incr = -incr;
+   }
    else if (start < end && incr < 0)
+   {
+     /* Make sure not evaluating -INTMAX_MIN. */
+     if (incr == INTMAX_MIN)
+     {
+       return ((char **)NULL);
+     }
+     
      incr = -incr;
!   }
!   
!   /* strvec_create argument is an int, so must make sure that the number of
!   elements in the sequence (imaxabs(end - start) + 1), + 1 for a NULL
!   terminator, does not overflow int. */
!   if (subtractwilloverflow(end, start, INTMAX_MIN + 1 + 2, INTMAX_MAX - 2)
!     ||
!     ((imaxabs(end - start) + 2) > INT_MAX))
!   {
!     return ((char **)NULL);
!   }
!   
!   i = imaxabs(end - start) + 1 + 1;
!   
!   /* Note: potentially allocating a lot more memory than required if
!    incr > 1. */
!   result = strvec_create (i);
!   
    /* Make sure we go through the loop at least once, so {3..3} prints `3' */
    i = 0;
    n = start;
***************
*** 349,354 ****
--- 396,409 ----
  	  t[1] = '\0';
  	  result[i++] = t;
  	}
+       
+       /* Can't increment n with incr before loop termination check, due to the
+        possibility of undefined signed integer overflow. */
+       if (addwilloverflow(n, incr, INTMAX_MIN, INTMAX_MAX))
+       {
+ 	break;
+       }
+       
        n += incr;
        if ((incr < 0 && n < end) || (incr > 0 && n > end))
  	break;
***************
*** 365,372 ****
       size_t tlen;
  {
    char *t, *lhs, *rhs;
!   int i, lhs_t, rhs_t, incr, lhs_l, rhs_l, width;
!   intmax_t lhs_v, rhs_v;
    intmax_t tl, tr;
    char **result, *ep, *oep;
  
--- 420,427 ----
       size_t tlen;
  {
    char *t, *lhs, *rhs;
!   int i, lhs_t, rhs_t, lhs_l, rhs_l, width;
!   intmax_t lhs_v, rhs_v, incr;
    intmax_t tl, tr;
    char **result, *ep, *oep;
  
***************
*** 396,404 ****
    if (ISDIGIT (rhs[0]) || ((rhs[0] == '+' || rhs[0] == '-') && ISDIGIT (rhs[1])))
      {
        rhs_t = ST_INT;
        tr = strtoimax (rhs, &ep, 10);
!       if (ep && *ep != 0 && *ep != '.')
! 	rhs_t = ST_BAD;			/* invalid */
      }
    else if (ISALPHA (rhs[0]) && (rhs[1] == 0 || rhs[1] == '.'))
      {
--- 451,460 ----
    if (ISDIGIT (rhs[0]) || ((rhs[0] == '+' || rhs[0] == '-') && ISDIGIT (rhs[1])))
      {
        rhs_t = ST_INT;
+       errno = 0;
        tr = strtoimax (rhs, &ep, 10);
!       if (errno || ep && *ep != 0 && *ep != '.')
! 	rhs_t = ST_BAD;			/* invalid or overflow */
      }
    else if (ISALPHA (rhs[0]) && (rhs[1] == 0 || rhs[1] == '.'))
      {
***************
*** 415,424 ****
    if (rhs_t != ST_BAD)
      {
        oep = ep;
        if (ep && *ep == '.' && ep[1] == '.' && ep[2])
  	incr = strtoimax (ep + 2, &ep, 10);
!       if (*ep != 0)
! 	rhs_t = ST_BAD;			/* invalid incr */
        tlen -= ep - oep;
      }
  
--- 471,481 ----
    if (rhs_t != ST_BAD)
      {
        oep = ep;
+       errno = 0;
        if (ep && *ep == '.' && ep[1] == '.' && ep[2])
  	incr = strtoimax (ep + 2, &ep, 10);
!       if (errno || *ep != 0)
! 	rhs_t = ST_BAD;			/* invalid or overflow */
        tlen -= ep - oep;
      }
  
