This is the mail archive of the newlib@sources.redhat.com mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

*sprintf bug (+patch)


When building GDB on current cygwin, the built GDB seg faults. After some investigation the reason is that recently the cygwin DLL has been exporting vasprintf from newlib, whereas previously it would use vasprintf from libiberty.

Some of the time this worked, but it just so happened that GDB, in a deterministic way would always seg fault in the same place. The reason was pretty coincidental: the _file member of a FILE pointing to the underlying fd was unset for the *sprintf family. Most of the times it was random memory. But in the failing case it was 0.

As a result isatty() of the fd succeeded since it was stdin (see libc/stdio/makebuf.c) and the FILE flags were set to be linebuffering, meaning that later in __sfvwrite() in libc/stdio/fvwrite.c, the wrong branch was taken and the code that does a special case check of the __SSTR flag was never hit. Instead it tried to access fp->_write, which for *sprintf was always set to 0, hence the seg fault.

The attached patch fixes this. I have checkin access to /cvs/src so can just check it straight in if that's easier.

Jifl

2003-02-04 Jonathan Larmour <jifl@eCosCentric.com>

* libc/stdio/vsprintf.c (vsprintf, _vsprintf_r): Set _file fd to
-1 to be sure it cannot later match a valid file fd causing
isatty() to return 1.
* libc/stdio/asprintf.c (asprintf, _asprintf_r): Ditto.
* libc/stdio/sprintf.c (sprintf, _sprintf_r): Ditto.
* libc/stdio/vasprintf.c (vasprintf, _vasprintf_r): Ditto.

--
eCosCentric http://www.eCosCentric.com/ <info@eCosCentric.com>
--[ "You can complain because roses have thorns, or you ]--
--[ can rejoice because thorns have roses." -Lincoln ]-- Opinions==mine
Index: libc/stdio/asprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/asprintf.c,v
retrieving revision 1.2
diff -u -5 -p -r1.2 asprintf.c
--- libc/stdio/asprintf.c	6 Jan 2003 20:51:25 -0000	1.2
+++ libc/stdio/asprintf.c	4 Feb 2003 10:43:47 -0000
@@ -45,10 +45,11 @@ _asprintf_r (ptr, strp, fmt, va_alist)
   /* mark a zero-length reallocatable buffer */
   f._flags = __SWR | __SSTR | __SMBF;
   f._bf._base = f._p = NULL;
   f._bf._size = f._w = 0;
   f._data = ptr;
+  f._file = -1;  /* No file. */
 #ifdef _HAVE_STDC
   va_start (ap, fmt);
 #else
   va_start (ap);
 #endif
@@ -78,10 +79,11 @@ asprintf (strp, fmt, va_alist)
   /* mark a zero-length reallocatable buffer */
   f._flags = __SWR | __SSTR | __SMBF;
   f._bf._base = f._p = NULL;
   f._bf._size = f._w = 0;
   f._data = _REENT;
+  f._file = -1;  /* No file. */
 #ifdef _HAVE_STDC
   va_start (ap, fmt);
 #else
   va_start (ap);
 #endif
Index: libc/stdio/sprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/sprintf.c,v
retrieving revision 1.3
diff -u -5 -p -r1.3 sprintf.c
--- libc/stdio/sprintf.c	7 Jan 2003 20:02:33 -0000	1.3
+++ libc/stdio/sprintf.c	4 Feb 2003 10:43:47 -0000
@@ -323,10 +323,11 @@ _sprintf_r (ptr, str, fmt, va_alist)
 
   f._flags = __SWR | __SSTR;
   f._bf._base = f._p = (unsigned char *) str;
   f._bf._size = f._w = INT_MAX;
   f._data = ptr;
+  f._file = -1;  /* No file. */
 #ifdef _HAVE_STDC
   va_start (ap, fmt);
 #else
   va_start (ap);
 #endif
@@ -354,10 +355,11 @@ sprintf (str, fmt, va_alist)
 
   f._flags = __SWR | __SSTR;
   f._bf._base = f._p = (unsigned char *) str;
   f._bf._size = f._w = INT_MAX;
   f._data = _REENT;
+  f._file = -1;  /* No file. */
 #ifdef _HAVE_STDC
   va_start (ap, fmt);
 #else
   va_start (ap);
 #endif
Index: libc/stdio/vasprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/vasprintf.c,v
retrieving revision 1.1
diff -u -5 -p -r1.1 vasprintf.c
--- libc/stdio/vasprintf.c	4 Jul 2002 18:56:17 -0000	1.1
+++ libc/stdio/vasprintf.c	4 Feb 2003 10:43:47 -0000
@@ -44,10 +44,11 @@ _DEFUN (vasprintf, (strp, fmt, ap),
 
   f._flags = __SWR | __SSTR | __SMBF;
   f._bf._base = f._p = NULL;
   f._bf._size = f._w = 0;
   f._data = _REENT;
+  f._file = -1;  /* No file. */
   ret = vfprintf (&f, fmt, ap);
   *f._p = 0;
   *strp = f._bf._base;
   return ret;
 }
@@ -64,10 +65,11 @@ _DEFUN (_vasprintf_r, (ptr, strp, fmt, a
 
   f._flags = __SWR | __SSTR | __SMBF ;
   f._bf._base = f._p = NULL;
   f._bf._size = f._w = 0;
   f._data = ptr;
+  f._file = -1;  /* No file. */
   ret = _vfprintf_r (ptr, &f, fmt, ap);
   *f._p = 0;
   *strp = f._bf._base;
   return ret;
 }
Index: libc/stdio/vsprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/vsprintf.c,v
retrieving revision 1.2
diff -u -5 -p -r1.2 vsprintf.c
--- libc/stdio/vsprintf.c	24 Apr 2001 22:09:21 -0000	1.2
+++ libc/stdio/vsprintf.c	4 Feb 2003 10:43:47 -0000
@@ -42,10 +42,11 @@ _DEFUN (vsprintf, (str, fmt, ap),
 
   f._flags = __SWR | __SSTR;
   f._bf._base = f._p = (unsigned char *) str;
   f._bf._size = f._w = INT_MAX;
   f._data = _REENT;
+  f._file = -1;  /* No file. */
   ret = vfprintf (&f, fmt, ap);
   *f._p = 0;
   return ret;
 }
 
@@ -61,10 +62,11 @@ _DEFUN (_vsprintf_r, (ptr, str, fmt, ap)
 
   f._flags = __SWR | __SSTR;
   f._bf._base = f._p = (unsigned char *) str;
   f._bf._size = f._w = INT_MAX;
   f._data = ptr;
+  f._file = -1;  /* No file. */
   ret = _vfprintf_r (ptr, &f, fmt, ap);
   *f._p = 0;
   return ret;
 }
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]