vasprintf bugs

Eric Blake ebb9@byu.net
Tue Mar 13 04:01:00 GMT 2007


Jeff Johnston <jjohnstn <at> redhat.com> writes:

> 
> Patch checked in.
> 
> Thanks,
> 

Thanks.  I noticed one more scenario where a malloc failure led to corruption 
in asprintf.

Also, Linux states that malloc failure in snprintf leaves *strp undefined, 
while BSD sets *strp to NULL.  Currently, newlib follows Linux; is there any 
desire to follow BSD or is that just code bloat?

Also, POSIX requires snprintf to fail if either the original buffer or the 
final computed size exceeds INT_MAX; a rather pointless limitation, but we 
might as well comply.  I propogated the limit to sniprintf (since it is 
sometimes used as a replacement snprintf), but left asprintf alone (since it is 
not specified by POSIX, it need not inherit the pointless limitation).

I still haven't gotten to implementing asnprintf.

2007-03-12  Eric Blake  <ebb9@byu.net>

	* libc/stdio/makebuf.c (__smakebuf): Detect failed allocation with
	asprintf.
	* libc/stdio/wsetup.c (__swsetup): Likewise.
	* libc/stdio/vfprintf.c (_VFPRINTF_R): Set errno properly on
	failed asprintf allocation.
	* libc/stdio/fvwrite.c (__sfvwrite_r): Likewise.
	* libc/stdio/snprintf.c (snprintf, _snprintf_r): Report overflow,
	as required by POSIX.
	* libc/stdio/sniprintf.c (sniprintf, _sniprintf_r): Likewise.
	* libc/stdio/vsnprintf.c (vsnprintf, _vsnprintf_r): Likewise.
	* libc/stdio/vsniprintf.c (vsniprintf, _vsniprintf_r): Likewise.

Index: libc/stdio/fvwrite.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/fvwrite.c,v
retrieving revision 1.10
diff -u -r1.10 fvwrite.c
--- libc/stdio/fvwrite.c	12 Mar 2007 20:30:08 -0000	1.10
+++ libc/stdio/fvwrite.c	13 Mar 2007 03:46:37 -0000
@@ -147,6 +147,7 @@
 		    {
 		      /* Free buffer which is no longer used.  */
 		      _free_r (ptr, fp->_bf._base);
+                      ptr->_errno = ENOMEM;
 		      goto err;
 		    }
 		  fp->_bf._base = str;
Index: libc/stdio/makebuf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/makebuf.c,v
retrieving revision 1.6
diff -u -r1.6 makebuf.c
--- libc/stdio/makebuf.c	30 Nov 2006 00:35:57 -0000	1.6
+++ libc/stdio/makebuf.c	13 Mar 2007 03:46:37 -0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1990, 2007 The Regents of the University of California.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms are permitted
@@ -89,9 +89,12 @@
     }
   if ((p = _malloc_r (_REENT, size)) == NULL)
     {
-      fp->_flags |= __SNBF;
-      fp->_bf._base = fp->_p = fp->_nbuf;
-      fp->_bf._size = 1;
+      if (!(fp->flags & __SSTR))
+	{
+	  fp->_flags |= __SNBF;
+	  fp->_bf._base = fp->_p = fp->_nbuf;
+	  fp->_bf._size = 1;
+	}
     }
   else
     {
Index: libc/stdio/sniprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/sniprintf.c,v
retrieving revision 1.2
diff -u -r1.2 sniprintf.c
--- libc/stdio/sniprintf.c	24 Nov 2004 00:45:41 -0000	1.2
+++ libc/stdio/sniprintf.c	13 Mar 2007 03:46:37 -0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1990, 2007 The Regents of the University of California.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms are permitted
@@ -59,6 +59,11 @@
 #endif
   ret = _vfiprintf_r (ptr, &f, fmt, ap);
   va_end (ap);
+  if (ret > INT_MAX)
+    {
+      ptr->_errno = EOVERFLOW;
+      return EOF;
+    }
   if (size > 0)
     *f._p = 0;
   return (ret);
@@ -95,6 +100,11 @@
 #endif
   ret = _vfiprintf_r (_REENT, &f, fmt, ap);
   va_end (ap);
+  if (ret > INT_MAX)
+    {
+      ptr->_errno = EOVERFLOW;
+      return EOF;
+    }
   if (size > 0)
     *f._p = 0;
   return (ret);
Index: libc/stdio/snprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/snprintf.c,v
retrieving revision 1.5
diff -u -r1.5 snprintf.c
--- libc/stdio/snprintf.c	16 Sep 2004 21:30:51 -0000	1.5
+++ libc/stdio/snprintf.c	13 Mar 2007 03:46:37 -0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1990, 2007 The Regents of the University of California.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms are permitted
@@ -59,6 +59,11 @@
 #endif
   ret = _vfprintf_r (ptr, &f, fmt, ap);
   va_end (ap);
+  if (ret > INT_MAX)
+    {
+      ptr->_errno = EOVERFLOW;
+      return EOF;
+    }
   if (size > 0)
     *f._p = 0;
   return (ret);
@@ -95,6 +100,11 @@
 #endif
   ret = _vfprintf_r (_REENT, &f, fmt, ap);
   va_end (ap);
+  if (ret > INT_MAX)
+    {
+      ptr->_errno = EOVERFLOW;
+      return EOF;
+    }
   if (size > 0)
     *f._p = 0;
   return (ret);
Index: libc/stdio/vfprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/vfprintf.c,v
retrieving revision 1.47
diff -u -r1.47 vfprintf.c
--- libc/stdio/vfprintf.c	14 Nov 2006 21:29:26 -0000	1.47
+++ libc/stdio/vfprintf.c	13 Mar 2007 03:46:37 -0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1990, 2006 The Regents of the University of California.
+ * Copyright (c) 1990, 2006, 2007 The Regents of the University of California.
  * All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
@@ -546,7 +546,10 @@
 	/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
 	if (cantwrite (fp)) {
 		_funlockfile (fp);	
-		return (EOF);
+                /* set errno on failed asprintf */
+                if (fp->_flags & __SSTR)
+                	ptr->_errno = ENOMEM;
+                return (EOF);
 	}
 
 	/* optimise fprintf(stderr) (and other unbuffered Unix files) */
Index: libc/stdio/vsniprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/vsniprintf.c,v
retrieving revision 1.1
diff -u -r1.1 vsniprintf.c
--- libc/stdio/vsniprintf.c	24 Nov 2004 00:45:41 -0000	1.1
+++ libc/stdio/vsniprintf.c	13 Mar 2007 03:46:37 -0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1990, 2007 The Regents of the University of California.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms are permitted
@@ -86,6 +86,11 @@
   f._bf._size = f._w = (size > 0 ? size - 1 : 0);
   f._file = -1;  /* No file. */
   ret = _vfiprintf_r (_REENT, &f, fmt, ap);
+  if (ret > INT_MAX)
+    {
+      ptr->_errno = EOVERFLOW;
+      return EOF;
+    }
   if (size > 0)
     *f._p = 0;
   return ret;
@@ -109,6 +114,11 @@
   f._bf._size = f._w = (size > 0 ? size - 1 : 0);
   f._file = -1;  /* No file. */
   ret = _vfiprintf_r (ptr, &f, fmt, ap);
+  if (ret > INT_MAX)
+    {
+      ptr->_errno = EOVERFLOW;
+      return EOF;
+    }
   if (size > 0)
     *f._p = 0;
   return ret;
Index: libc/stdio/vsnprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/vsnprintf.c,v
retrieving revision 1.6
diff -u -r1.6 vsnprintf.c
--- libc/stdio/vsnprintf.c	16 Sep 2004 21:30:51 -0000	1.6
+++ libc/stdio/vsnprintf.c	13 Mar 2007 03:46:37 -0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1990, 2007 The Regents of the University of California.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms are permitted
@@ -47,6 +47,11 @@
   f._bf._size = f._w = (size > 0 ? size - 1 : 0);
   f._file = -1;  /* No file. */
   ret = _vfprintf_r (_REENT, &f, fmt, ap);
+  if (ret > INT_MAX)
+    {
+      ptr->_errno = EOVERFLOW;
+      return EOF;
+    }
   if (size > 0)
     *f._p = 0;
   return ret;
@@ -70,6 +75,11 @@
   f._bf._size = f._w = (size > 0 ? size - 1 : 0);
   f._file = -1;  /* No file. */
   ret = _vfprintf_r (ptr, &f, fmt, ap);
+  if (ret > INT_MAX)
+    {
+      ptr->_errno = EOVERFLOW;
+      return EOF;
+    }
   if (size > 0)
     *f._p = 0;
   return ret;
Index: libc/stdio/wsetup.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/wsetup.c,v
retrieving revision 1.5
diff -u -r1.5 wsetup.c
--- libc/stdio/wsetup.c	26 Sep 2006 21:22:19 -0000	1.5
+++ libc/stdio/wsetup.c	13 Mar 2007 03:46:37 -0000
@@ -1,7 +1,7 @@
 /* No user fns here. Pesch 15apr92. */
 
 /*
- * Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1990, 2007 The Regents of the University of California.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms are permitted
@@ -78,5 +78,5 @@
   else
     fp->_w = fp->_flags & __SNBF ? 0 : fp->_bf._size;
 
-  return 0;
+  return fp->_bf._base ? 0 : EOF;
 }





More information about the Newlib mailing list