*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