This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
Re: vasprintf bugs
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;
}