*sprintf bug (+patch)
J. Johnston
jjohnstn@redhat.com
Wed Feb 5 16:52:00 GMT 2003
Patch applied. Thanks.
-- Jeff J.
Jonathan Larmour wrote:
> 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.
>
>
> ------------------------------------------------------------------------
>
> 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;
> }
>
More information about the Newlib
mailing list