Blob Blame History Raw
--- a/stdio-common/vfprintf.c	2012-03-07 12:16:21.000000000 -0700
+++ b/stdio-common/vfprintf.c	2012-03-07 12:00:28.006630851 -0700
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2008, 2009, 2010, 2011   Free Software Foundation, Inc.
+/* Copyright (C) 1991-2011, 2012   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -12,9 +12,8 @@
    Lesser General Public License for more details.
 
    You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
 
 #include <ctype.h>
 #include <limits.h>
@@ -823,7 +822,7 @@ vfprintf (FILE *s, const CHAR_T *format,
 									      \
 	if (function_done < 0)						      \
 	  {								      \
-	    /* Error in print handler.  */				      \
+	    /* Error in print handler; up to handler to set errno.  */	      \
 	    done = -1;							      \
 	    goto all_done;						      \
 	  }								      \
@@ -877,7 +876,7 @@ vfprintf (FILE *s, const CHAR_T *format,
 									      \
 	if (function_done < 0)						      \
 	  {								      \
-	    /* Error in print handler.  */				      \
+	    /* Error in print handler; up to handler to set errno.  */	      \
 	    done = -1;							      \
 	    goto all_done;						      \
 	  }								      \
@@ -1118,7 +1117,7 @@ vfprintf (FILE *s, const CHAR_T *format,
 			 &mbstate);					      \
 	if (len == (size_t) -1)						      \
 	  {								      \
-	    /* Something went wron gduring the conversion.  Bail out.  */     \
+	    /* Something went wrong during the conversion.  Bail out.  */     \
 	    done = -1;							      \
 	    goto all_done;						      \
 	  }								      \
@@ -1574,6 +1606,7 @@ vfprintf (FILE *s, const CHAR_T *format,
 	  if (spec == L_('\0'))
 	    {
 	      /* The format string ended before the specifier is complete.  */
+	      __set_errno (EINVAL);
 	      done = -1;
 	      goto all_done;
 	    }
@@ -1671,29 +1704,34 @@ do_positional:
 
     /* Determine the number of arguments the format string consumes.  */
     nargs = MAX (nargs, max_ref_arg);
-    bytes_per_arg = sizeof (*args_value) + sizeof (*args_size)
-                    + sizeof (*args_type);
+    /* Calculate total size needed to represent a single argument across
+       all three argument-related arrays.  */
+    bytes_per_arg = (sizeof (*args_value) + sizeof (*args_size)
+		     + sizeof (*args_type));
 
     /* Check for potential integer overflow.  */
-    if (nargs > SIZE_MAX / bytes_per_arg)
+    if (__builtin_expect (nargs > SIZE_MAX / bytes_per_arg, 0))
       {
-         done = -1;
-         goto all_done;
+	 __set_errno (ERANGE);
+	 done = -1;
+	 goto all_done;
       }
 
-    /* Allocate memory for the argument descriptions.  */
+    /* Allocate memory for all three argument arrays.  */
     if (__libc_use_alloca (nargs * bytes_per_arg))
-        args_value = alloca (nargs * bytes_per_arg);
+	args_value = alloca (nargs * bytes_per_arg);
     else
       {
-        args_value = args_malloced = malloc (nargs * bytes_per_arg);
-        if (args_value == NULL)
-          {
-            done = -1;
-            goto all_done;
-          }
+	args_value = args_malloced = malloc (nargs * bytes_per_arg);
+	if (args_value == NULL)
+	  {
+	    done = -1;
+	    goto all_done;
+	  }
       }
 
+    /* Set up the remaining two arrays to each point past the end of the
+       prior array, since space for all three has been allocated now.  */
     args_size = &args_value[nargs].pa_int;
     args_type = &args_size[nargs];
     memset (args_type, s->_flags2 & _IO_FLAGS2_FORTIFY ? '\xff' : '\0',
@@ -1912,6 +1950,7 @@ do_positional:
 		       about # of chars.  */
 		    if (function_done < 0)
 		      {
+			/* Function has set errno.  */
 			done = -1;
 			goto all_done;
 		      }
@@ -1946,6 +1985,7 @@ do_positional:
 		 of chars.  */
 	      if (function_done < 0)
 		{
+		  /* Function has set errno.  */
 		  done = -1;
 		  goto all_done;
 		}