File glibc-2.11-strfmon.diff of Package glibc.i686

2009-04-18  Ulrich Drepper  <drepper@redhat.com>
 
	* stdlib/strfmon_l.c (__vstrfmon_l): Don't wrap when computing width.
	Numerically stable check for valid width.

diff --git a/stdlib/strfmon_l.c b/stdlib/strfmon_l.c
index c9f3a47..8e63d45 100644
--- a/stdlib/strfmon_l.c
+++ b/stdlib/strfmon_l.c
@@ -1,5 +1,5 @@
 /* Formatting a monetary value according to the given locale.
-   Copyright (C) 1996, 1997, 2002, 2004, 2006 Free Software Foundation, Inc.
+   Copyright (C) 1996,1997,2002,2004,2006,2009 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
 
@@ -133,7 +133,7 @@ __vstrfmon_l (char *s, size_t maxsize, __locale_t loc, const char *format,
       int done;
       const char *currency_symbol;
       size_t currency_symbol_len;
-      int width;
+      long int width;
       char *startp;
       const void *ptr;
       char space_char;
@@ -221,13 +221,21 @@ __vstrfmon_l (char *s, size_t maxsize, __locale_t loc, const char *format,
 
 	  while (isdigit (*++fmt))
 	    {
-	      width *= 10;
-	      width += to_digit (*fmt);
+	      int val = to_digit (*fmt);
+
+	      if (width > LONG_MAX / 10
+		  || (width == LONG_MAX && val > LONG_MAX % 10))
+		{
+		  __set_errno (E2BIG);
+		  return -1;
+		}
+
+	      width = width * 10 + val;
 	    }
 
 	  /* If we don't have enough room for the demanded width we
 	     can stop now and return an error.  */
-	  if (dest + width >= s + maxsize)
+	  if (width >= maxsize - (dest - s))
 	    {
 	      __set_errno (E2BIG);
 	      return -1;
@@ -589,9 +597,8 @@ __vstrfmon_l (char *s, size_t maxsize, __locale_t loc, const char *format,
 	    while (dest - startp < width);
 	  else
 	    {
-	      int dist = width - (dest - startp);
-	      char *cp;
-	      for (cp = dest - 1; cp >= startp; --cp)
+	      long int dist = width - (dest - startp);
+	      for (char *cp = dest - 1; cp >= startp; --cp)
 		cp[dist] = cp[0];
 
 	      dest += dist;


2009-09-28  Andreas Schwab  <schwab@redhat.com>

	* stdio-common/printf_fp.c: Check for and avoid integer overflows.
	* stdio-common/vfprintf.c: Likewise.

diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c
index cd3ada6..b60ddec 100644
--- a/stdio-common/printf_fp.c
+++ b/stdio-common/printf_fp.c
@@ -891,8 +891,15 @@ ___printf_fp (FILE *fp,
        it is possible that we need two more characters in front of all the
        other output.  If the amount of memory we have to allocate is too
        large use `malloc' instead of `alloca'.  */
-    size_t wbuffer_to_alloc = (2 + (size_t) chars_needed) * sizeof (wchar_t);
-    buffer_malloced = ! __libc_use_alloca (chars_needed * 2 * sizeof (wchar_t));
+    if (__builtin_expect (chars_needed >= (size_t) -1 / sizeof (wchar_t) - 2
+			  || chars_needed < fracdig_max, 0))
+      {
+	/* Some overflow occurred.  */
+	__set_errno (ERANGE);
+	return -1;
+      }
+    size_t wbuffer_to_alloc = (2 + chars_needed) * sizeof (wchar_t);
+    buffer_malloced = ! __libc_use_alloca (wbuffer_to_alloc);
     if (__builtin_expect (buffer_malloced, 0))
       {
 	wbuffer = (wchar_t *) malloc (wbuffer_to_alloc);
diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c
index 38ba8ff..6e0e85c 100644
--- a/stdio-common/vfprintf.c
+++ b/stdio-common/vfprintf.c
@@ -1439,23 +1439,29 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 	    left = 1;
 	  }
 
-	if (width + 32 >= (int) (sizeof (work_buffer)
-				 / sizeof (work_buffer[0])))
+	if (__builtin_expect (width >= (size_t) -1 / sizeof (CHAR_T) - 32, 0))
+	  {
+	    __set_errno (ERANGE);
+	    done = -1;
+	    goto all_done;
+	  }
+
+	if (width >= sizeof (work_buffer) / sizeof (work_buffer[0]) - 32)
 	  {
 	    /* We have to use a special buffer.  The "32" is just a safe
 	       bet for all the output which is not counted in the width.  */
-	    if (__libc_use_alloca ((width + 32) * sizeof (CHAR_T)))
-	      workend = ((CHAR_T *) alloca ((width + 32) * sizeof (CHAR_T))
-			 + (width + 32));
+	    size_t needed = ((size_t) width + 32) * sizeof (CHAR_T);
+	    if (__libc_use_alloca (needed))
+	      workend = (CHAR_T *) alloca (needed) + width + 32;
 	    else
 	      {
-		workstart = (CHAR_T *) malloc ((width + 32) * sizeof (CHAR_T));
+		workstart = (CHAR_T *) malloc (needed);
 		if (workstart == NULL)
 		  {
 		    done = -1;
 		    goto all_done;
 		  }
-		workend = workstart + (width + 32);
+		workend = workstart + width + 32;
 	      }
 	  }
       }
@@ -1465,22 +1471,29 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
     LABEL (width):
       width = read_int (&f);
 
-      if (width + 32 >= (int) (sizeof (work_buffer) / sizeof (work_buffer[0])))
+      if (__builtin_expect (width >= (size_t) -1 / sizeof (CHAR_T) - 32, 0))
+	{
+	  __set_errno (ERANGE);
+	  done = -1;
+	  goto all_done;
+	}
+
+      if (width >= sizeof (work_buffer) / sizeof (work_buffer[0]) - 32)
 	{
 	  /* We have to use a special buffer.  The "32" is just a safe
 	     bet for all the output which is not counted in the width.  */
-	  if (__libc_use_alloca ((width + 32) * sizeof (CHAR_T)))
-	    workend = ((CHAR_T *) alloca ((width + 32) * sizeof (CHAR_T))
-		       + (width + 32));
+	  size_t needed = ((size_t) width + 32) * sizeof (CHAR_T);
+	  if (__libc_use_alloca (needed))
+	    workend = (CHAR_T *) alloca (needed) + width + 32;
 	  else
 	    {
-	      workstart = (CHAR_T *) malloc ((width + 32) * sizeof (CHAR_T));
+	      workstart = (CHAR_T *) malloc (needed);
 	      if (workstart == NULL)
 		{
 		  done = -1;
 		  goto all_done;
 		}
-	      workend = workstart + (width + 32);
+	      workend = workstart + width + 32;
 	    }
 	}
       if (*f == L_('$'))
@@ -1510,18 +1523,18 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
       else
 	prec = 0;
       if (prec > width
-	  && prec + 32 > (int)(sizeof (work_buffer) / sizeof (work_buffer[0])))
+	  && prec > sizeof (work_buffer) / sizeof (work_buffer[0]) - 32)
 	{
-	  if (__builtin_expect (prec > ~((size_t) 0) / sizeof (CHAR_T) - 31,
-				0))
+	  if (__builtin_expect (prec >= (size_t) -1 / sizeof (CHAR_T) - 32, 0))
 	    {
+	      __set_errno (ERANGE);
 	      done = -1;
 	      goto all_done;
 	    }
 	  size_t needed = ((size_t) prec + 32) * sizeof (CHAR_T);
 
 	  if (__libc_use_alloca (needed))
-	    workend = (((CHAR_T *) alloca (needed)) + ((size_t) prec + 32));
+	    workend = (CHAR_T *) alloca (needed) + prec + 32;
 	  else
 	    {
 	      workstart = (CHAR_T *) malloc (needed);
@@ -1530,7 +1543,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 		  done = -1;
 		  goto all_done;
 		}
-	      workend = workstart + ((size_t) prec + 32);
+	      workend = workstart + prec + 32;
 	    }
 	}
       JUMP (*f, step2_jumps);
openSUSE Build Service is sponsored by