*printf_r and reentrancy

Jeff Johnston jjohnstn@redhat.com
Wed Mar 14 18:24:00 GMT 2007


Eric Blake wrote:
> Jeff Johnston <jjohnstn <at> redhat.com> writes:
> 
>> There are some __ functions exposed via macros in newlib headers. 
>> Normally, you just create an _r version of the function and if the 
>> regular version needs to be around (e.g. is exposed via a macro), then 
>> have the regular version call the _r routine with _REENT as a parameter.
>> The ones mentioned so far to be changed are all fine.
>>
> 
> What about refill.c, for example?  __srefill_r was using __smakebuf, so that 
> needed to be made reentrant.  But it also calls _fwalk(_GLOBAL_REENT, lflush), 
> which in turn calls fflush, which starts out with CHECK_INIT(_REENT, fp).  A 
> quick grep showed several uses of fflush in *_r functions, even though there is 
> not yet fflush_r; but within fflush, the only use of the reentrancy structure 
> was CHECK_INIT.  Does that mean I need a followup patch that implements 
> _fwalk_r and _fflush_r?
> 

The _fwalk call is meant to use the _GLOBAL_REENT input and only that 
input (it has the file chain).

fflush is currently fine because CHECK_INIT is designed for the std 
streams and the std streams are defined as being _REENT based (see 
stdio.h).  Internal callers to fflush already have CHECK_INIT tests 
which properly use the reent struct for the input file given.

In the case where a platform uses the _stdin_r, _stdout_r, or _stderr_r 
macros and the first call is to fflush, this is usually fine because 
fflush will simply lock the file and realize there is nothing to do and 
exit.  In the case of a _REENT_SMALL platform, there is a hitch.  In 
this case, fflush will run CHECK_INIT on _REENT instead of the given 
reentrancy struct.  The CHECK_INIT will realize that the file points to 
one of the fake std streams and it will replace the file pointer with 
stdin, stdout, and stderr (_REENT based again).  If the _REENT std 
streams have operations on them, fflush will perform an action on them. 
  Otherwise, nothing happens, as to be expected.

There is an extreme low probability of a _REENT_SMALL platform even 
using multiple reent structures as they are extremely tight for space.

A simple fix to this problem is to add a check for the fake file 
structures in fflush (_REENT_SMALL only) and return immediately without 
doing anything.  The CHECK_INIT macro for _REENT_SMALL should be altered 
to use the std streams for the given reentrancy struct when reassigning 
the file pointer.

> Meanwhile, here's a patch that should be ready to apply, to fix up malloc 
> failure with asprintf, and the followon reentrancy fix to any of the stdio 
> files that used malloc/free via __smakebuf.  Tested by compiling and running 
> cygwin, although it is rather hard testing malloc failure, so a double-check 
> wouldn't hurt.
> 
> 2007-03-13  Eric Blake  <ebb9@byu.net>
> 
> 	* libc/stdio/local.h (cantwrite, FREEUB, FREELB): Make reentrant.
> 	(__smakebuf): Rename...
> 	(__smakebuf_r): to this.
> 	* libc/stdio/fvwrite.h (__swsetup_r): Rename, from __swsetup.
> 	* libc/stdio/makebuf.c (__smakebuf): Detect failed asprint
> 	allocation, then rename...
> 	(__smakebuf_r): ...to this and fix reentrancy.
> 	* libc/stdio/wsetup.c (__swsetup): Detect failed asprintf
> 	allocation, then rename...
> 	(__swsetup_r): ...to this and fix reentrancy.
> 	* libc/stdio/fseek.c (_fseek_r): Fix reentrancy.
> 	* libc/stdio/refill.c (__srefill_r): Likewise.
> 	* libc/stdio/fclose.c (_fclose_r): Likewise.
> 	* libc/stdio/fread.c (_fread_r): Likewise.
> 	* libc/stdio/freopen.c (_freopen_r): Likewise.
> 	* libc/stdio/wbuf.c (__swbuf_r): Likewise.
> 	* libc/stdio64/fseeko64.c (_fseeko64_r): Likewise.
> 	* libc/stdio/fvwrite.c (__sfvwrite_r): Set errno properly on
> 	failed asprintf allocation, and fix reentrancy.
> 	* 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/fclose.c
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio/fclose.c,v
> retrieving revision 1.12
> diff -u -r1.12 fclose.c
> --- libc/stdio/fclose.c	14 Dec 2006 22:47:12 -0000	1.12
> +++ libc/stdio/fclose.c	13 Mar 2007 23:05:09 -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
> @@ -95,9 +95,9 @@
>    if (fp->_flags & __SMBF)
>      _free_r (rptr, (char *) fp->_bf._base);
>    if (HASUB (fp))
> -    FREEUB (fp);
> +    FREEUB (rptr, fp);
>    if (HASLB (fp))
> -    FREELB (fp);
> +    FREELB (rptr, fp);
>    fp->_flags = 0;		/* release this FILE for reuse */
>    _funlockfile (fp);
>  #ifndef __SINGLE_THREAD__
> @@ -119,4 +119,3 @@
>  }
>  
>  #endif
> -
> Index: libc/stdio/fread.c
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio/fread.c,v
> retrieving revision 1.13
> diff -u -r1.13 fread.c
> --- libc/stdio/fread.c	26 Sep 2006 21:22:19 -0000	1.13
> +++ libc/stdio/fread.c	13 Mar 2007 23:05:09 -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
> @@ -168,7 +168,7 @@
>  
>        /* If still more data needed, free any allocated ungetc buffer.  */
>        if (HASUB (fp) && resid > 0)
> -	FREEUB (fp);
> +	FREEUB (ptr, fp);
>  
>        /* Finally read directly into user's buffer if needed.  */
>        while (resid > 0)
> Index: libc/stdio/freopen.c
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio/freopen.c,v
> retrieving revision 1.18
> diff -u -r1.18 freopen.c
> --- libc/stdio/freopen.c	26 Sep 2006 21:22:19 -0000	1.18
> +++ libc/stdio/freopen.c	13 Mar 2007 23:05:09 -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.
>   *
>   * Redistribution and use in source and binary forms are permitted
> @@ -196,10 +196,10 @@
>    fp->_bf._size = 0;
>    fp->_lbfsize = 0;
>    if (HASUB (fp))
> -    FREEUB (fp);
> +    FREEUB (ptr, fp);
>    fp->_ub._size = 0;
>    if (HASLB (fp))
> -    FREELB (fp);
> +    FREELB (ptr, fp);
>    fp->_lb._size = 0;
>  
>    if (f < 0)
> Index: libc/stdio/fseek.c
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio/fseek.c,v
> retrieving revision 1.14
> diff -u -r1.14 fseek.c
> --- libc/stdio/fseek.c	26 Sep 2006 21:22:19 -0000	1.14
> +++ libc/stdio/fseek.c	13 Mar 2007 23:05:09 -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
> @@ -213,7 +213,7 @@
>     */
>  
>    if (fp->_bf._base == NULL)
> -    __smakebuf (fp);
> +    __smakebuf_r (ptr, fp);
>    if (fp->_flags & (__SWR | __SRW | __SNBF | __SNPT))
>      goto dumb;
>    if ((fp->_flags & __SOPT) == 0)
> @@ -307,7 +307,7 @@
>        fp->_p = fp->_bf._base + o;
>        fp->_r = n - o;
>        if (HASUB (fp))
> -	FREEUB (fp);
> +	FREEUB (ptr, fp);
>        fp->_flags &= ~__SEOF;
>        _funlockfile (fp);
>        return 0;
> @@ -328,7 +328,7 @@
>    fp->_r = 0;
>    fp->_p = fp->_bf._base;
>    if (HASUB (fp))
> -    FREEUB (fp);
> +    FREEUB (ptr, fp);
>    fp->_flags &= ~__SEOF;
>    n = target - curoff;
>    if (n)
> @@ -354,7 +354,7 @@
>      }
>    /* success: clear EOF indicator and discard ungetc() data */
>    if (HASUB (fp))
> -    FREEUB (fp);
> +    FREEUB (ptr, fp);
>    fp->_p = fp->_bf._base;
>    fp->_r = 0;
>    /* fp->_w = 0; *//* unnecessary (I think...) */
> 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 23:05:09 -0000
> @@ -60,7 +60,7 @@
>      return 0;
>  
>    /* make sure we can write */
> -  if (cantwrite (fp))
> +  if (cantwrite (ptr, fp))
>      {
>        fp->_flags |= __SERR;
>        ptr->_errno = EBADF;
> @@ -147,6 +147,8 @@
>  		    {
>  		      /* Free buffer which is no longer used.  */
>  		      _free_r (ptr, fp->_bf._base);
> +                      /* Ensure correct errno, even if free changed it.  */
> +                      ptr->_errno = ENOMEM;
>  		      goto err;
>  		    }
>  		  fp->_bf._base = str;
> Index: libc/stdio/fvwrite.h
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio/fvwrite.h,v
> retrieving revision 1.2
> diff -u -r1.2 fvwrite.h
> --- libc/stdio/fvwrite.h	14 Jun 2006 20:49:11 -0000	1.2
> +++ libc/stdio/fvwrite.h	13 Mar 2007 23:05:09 -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
> @@ -33,6 +33,4 @@
>  
>  
>  extern int _EXFUN(__sfvwrite_r,(struct _reent *, FILE *, struct __suio *));
> -extern int _EXFUN(__swsetup,(FILE *));
> -
> -
> +extern int _EXFUN(__swsetup_r,(struct _reent *, FILE *));
> Index: libc/stdio/local.h
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio/local.h,v
> retrieving revision 1.18
> diff -u -r1.18 local.h
> --- libc/stdio/local.h	26 Sep 2006 21:22:19 -0000	1.18
> +++ libc/stdio/local.h	13 Mar 2007 23:05:09 -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
> @@ -41,7 +41,7 @@
>  extern int    _EXFUN(__stextmode,(int));
>  extern _VOID   _EXFUN(__sinit,(struct _reent *));
>  extern _VOID   _EXFUN(_cleanup_r,(struct _reent *));
> -extern _VOID   _EXFUN(__smakebuf,(FILE *));
> +extern _VOID   _EXFUN(__smakebuf_r,(struct _reent *, FILE *));
>  extern int    _EXFUN(_fwalk,(struct _reent *, int (*)(FILE *)));
>  extern int    _EXFUN(_fwalk_reent,(struct _reent *, int (*)(struct _reent *, 
> FILE *)));
>  struct _glue * _EXFUN(__sfmoreglue,(struct _reent *,int n));
> @@ -82,24 +82,25 @@
>  
>  /* Return true iff the given FILE cannot be written now.  */
>  
> -#define	cantwrite(fp) \
> +#define	cantwrite(ptr, fp)                                     \
>    ((((fp)->_flags & __SWR) == 0 || (fp)->_bf._base == NULL) && \
> -   __swsetup(fp))
> +   __swsetup_r(ptr, fp))
>  
>  /* Test whether the given stdio file has an active ungetc buffer;
>     release such a buffer, without restoring ordinary unread data.  */
>  
>  #define	HASUB(fp) ((fp)->_ub._base != NULL)
> -#define	FREEUB(fp) { \
> +#define	FREEUB(ptr, fp) {                    \
>  	if ((fp)->_ub._base != (fp)->_ubuf) \
> -		_free_r(_REENT, (char *)(fp)->_ub._base); \
> +		_free_r(ptr, (char *)(fp)->_ub._base); \
>  	(fp)->_ub._base = NULL; \
>  }
>  
>  /* Test for an fgetline() buffer.  */
>  
>  #define	HASLB(fp) ((fp)->_lb._base != NULL)
> -#define	FREELB(fp) { _free_r(_REENT,(char *)(fp)->_lb._base); (fp)-
>> _lb._base = NULL; }
> +#define	FREELB(ptr, fp) { _free_r(ptr,(char *)(fp)->_lb._base); \
> +      (fp)->_lb._base = NULL; }
>  
>  /* WARNING: _dcvt is defined in the stdlib directory, not here!  */
>  
> 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 23:05:09 -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
> @@ -35,7 +35,8 @@
>   */
>  
>  _VOID
> -_DEFUN(__smakebuf, (fp),
> +_DEFUN(__smakebuf_r, (ptr, fp),
> +       struct _reent *ptr _AND
>         register FILE *fp)
>  {
>    register size_t size, couldbetty;
> @@ -49,9 +50,9 @@
>        return;
>      }
>  #ifdef __USE_INTERNAL_STAT64
> -  if (fp->_file < 0 || _fstat64_r (_REENT, fp->_file, &st) < 0)
> +  if (fp->_file < 0 || _fstat64_r (ptr, fp->_file, &st) < 0)
>  #else
> -  if (fp->_file < 0 || _fstat_r (_REENT, fp->_file, &st) < 0)
> +  if (fp->_file < 0 || _fstat_r (ptr, fp->_file, &st) < 0)
>  #endif
>      {
>        couldbetty = 0;
> @@ -87,15 +88,18 @@
>        else
>  	fp->_flags |= __SNPT;
>      }
> -  if ((p = _malloc_r (_REENT, size)) == NULL)
> +  if ((p = _malloc_r (ptr, 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
>      {
> -      _REENT->__cleanup = _cleanup_r;
> +      ptr->__cleanup = _cleanup_r;
>        fp->_flags |= __SMBF;
>        fp->_bf._base = fp->_p = (unsigned char *) p;
>        fp->_bf._size = size;
> Index: libc/stdio/refill.c
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio/refill.c,v
> retrieving revision 1.8
> diff -u -r1.8 refill.c
> --- libc/stdio/refill.c	26 Sep 2006 21:22:19 -0000	1.8
> +++ libc/stdio/refill.c	13 Mar 2007 23:05:09 -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
> @@ -43,7 +43,7 @@
>  {
>    /* make sure stdio is set up */
>  
> -  CHECK_INIT (_REENT, fp);
> +  CHECK_INIT (ptr, fp);
>  
>    fp->_r = 0;			/* largely a convenience for callers */
>  
> @@ -83,7 +83,7 @@
>         */
>        if (HASUB (fp))
>  	{
> -	  FREEUB (fp);
> +	  FREEUB (ptr, fp);
>  	  if ((fp->_r = fp->_ur) != 0)
>  	    {
>  	      fp->_p = fp->_up;
> @@ -93,7 +93,7 @@
>      }
>  
>    if (fp->_bf._base == NULL)
> -    __smakebuf (fp);
> +    __smakebuf_r (ptr, fp);
>  
>    /*
>     * Before reading from a line buffered or unbuffered file,
> 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 23:05:09 -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
> @@ -26,6 +26,7 @@
>  #include <varargs.h>
>  #endif
>  #include <limits.h>
> +#include <errno.h>
>  #include "local.h"
>  
>  int
> @@ -48,6 +49,11 @@
>    va_list ap;
>    FILE f;
>  
> +  if (size > INT_MAX)
> +    {
> +      ptr->_errno = EOVERFLOW;
> +      return EOF;
> +    }
>    f._flags = __SWR | __SSTR;
>    f._bf._base = f._p = (unsigned char *) str;
>    f._bf._size = f._w = (size > 0 ? size - 1 : 0);
> @@ -59,6 +65,8 @@
>  #endif
>    ret = _vfiprintf_r (ptr, &f, fmt, ap);
>    va_end (ap);
> +  if (ret < EOF)
> +    ptr->_errno = EOVERFLOW;
>    if (size > 0)
>      *f._p = 0;
>    return (ret);
> @@ -83,7 +91,13 @@
>    int ret;
>    va_list ap;
>    FILE f;
> +  struct _reent *ptr = _REENT;
>  
> +  if (size > INT_MAX)
> +    {
> +      ptr->_errno = EOVERFLOW;
> +      return EOF;
> +    }
>    f._flags = __SWR | __SSTR;
>    f._bf._base = f._p = (unsigned char *) str;
>    f._bf._size = f._w = (size > 0 ? size - 1 : 0);
> @@ -93,8 +107,10 @@
>  #else
>    va_start (ap);
>  #endif
> -  ret = _vfiprintf_r (_REENT, &f, fmt, ap);
> +  ret = _vfiprintf_r (ptr, &f, fmt, ap);
>    va_end (ap);
> +  if (ret < EOF)
> +    ptr->_errno = EOVERFLOW;
>    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 23:05:09 -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
> @@ -26,6 +26,7 @@
>  #include <varargs.h>
>  #endif
>  #include <limits.h>
> +#include <errno.h>
>  #include "local.h"
>  
>  int
> @@ -48,6 +49,11 @@
>    va_list ap;
>    FILE f;
>  
> +  if (size > INT_MAX)
> +    {
> +      ptr->_errno = EOVERFLOW;
> +      return EOF;
> +    }
>    f._flags = __SWR | __SSTR;
>    f._bf._base = f._p = (unsigned char *) str;
>    f._bf._size = f._w = (size > 0 ? size - 1 : 0);
> @@ -59,6 +65,8 @@
>  #endif
>    ret = _vfprintf_r (ptr, &f, fmt, ap);
>    va_end (ap);
> +  if (ret < EOF)
> +    ptr->_errno = EOVERFLOW;
>    if (size > 0)
>      *f._p = 0;
>    return (ret);
> @@ -83,7 +91,13 @@
>    int ret;
>    va_list ap;
>    FILE f;
> +  struct _reent *ptr = _REENT;
>  
> +  if (size > INT_MAX)
> +    {
> +      ptr->_errno = EOVERFLOW;
> +      return EOF;
> +    }
>    f._flags = __SWR | __SSTR;
>    f._bf._base = f._p = (unsigned char *) str;
>    f._bf._size = f._w = (size > 0 ? size - 1 : 0);
> @@ -93,8 +107,10 @@
>  #else
>    va_start (ap);
>  #endif
> -  ret = _vfprintf_r (_REENT, &f, fmt, ap);
> +  ret = _vfprintf_r (ptr, &f, fmt, ap);
>    va_end (ap);
> +  if (ret < EOF)
> +    ptr->_errno = EOVERFLOW;
>    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 23:05:09 -0000
> @@ -544,7 +544,7 @@
>  	_flockfile (fp);
>  
>  	/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
> -	if (cantwrite (fp)) {
> +	if (cantwrite (data, fp)) {
>  		_funlockfile (fp);	
>  		return (EOF);
>  	}
> 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 23:05:09 -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
> @@ -68,6 +68,7 @@
>  #else
>  #include <varargs.h>
>  #endif
> +#include <errno.h>
>  
>  #ifndef _REENT_ONLY
>  
> @@ -80,12 +81,20 @@
>  {
>    int ret;
>    FILE f;
> +  struct _reent *ptr = _REENT;
>  
> +  if (size > INT_MAX)
> +    {
> +      ptr->_errno = EOVERFLOW;
> +      return EOF;
> +    }
>    f._flags = __SWR | __SSTR;
>    f._bf._base = f._p = (unsigned char *) str;
>    f._bf._size = f._w = (size > 0 ? size - 1 : 0);
>    f._file = -1;  /* No file. */
> -  ret = _vfiprintf_r (_REENT, &f, fmt, ap);
> +  ret = _vfiprintf_r (ptr, &f, fmt, ap);
> +  if (ret < EOF)
> +    ptr->_errno = EOVERFLOW;
>    if (size > 0)
>      *f._p = 0;
>    return ret;
> @@ -104,11 +113,18 @@
>    int ret;
>    FILE f;
>  
> +  if (size > INT_MAX)
> +    {
> +      ptr->_errno = EOVERFLOW;
> +      return EOF;
> +    }
>    f._flags = __SWR | __SSTR;
>    f._bf._base = f._p = (unsigned char *) str;
>    f._bf._size = f._w = (size > 0 ? size - 1 : 0);
>    f._file = -1;  /* No file. */
>    ret = _vfiprintf_r (ptr, &f, fmt, ap);
> +  if (ret < EOF)
> +    ptr->_errno = EOVERFLOW;
>    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 23:05:09 -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
> @@ -29,6 +29,7 @@
>  #else
>  #include <varargs.h>
>  #endif
> +#include <errno.h>
>  
>  #ifndef _REENT_ONLY
>  
> @@ -41,12 +42,20 @@
>  {
>    int ret;
>    FILE f;
> +  struct _reent *ptr = _REENT;
>  
> +  if (size > INT_MAX)
> +    {
> +      ptr->_errno = EOVERFLOW;
> +      return EOF;
> +    }
>    f._flags = __SWR | __SSTR;
>    f._bf._base = f._p = (unsigned char *) str;
>    f._bf._size = f._w = (size > 0 ? size - 1 : 0);
>    f._file = -1;  /* No file. */
> -  ret = _vfprintf_r (_REENT, &f, fmt, ap);
> +  ret = _vfprintf_r (ptr, &f, fmt, ap);
> +  if (ret < EOF)
> +    ptr->_errno = EOVERFLOW;
>    if (size > 0)
>      *f._p = 0;
>    return ret;
> @@ -65,11 +74,18 @@
>    int ret;
>    FILE f;
>  
> +  if (size > INT_MAX)
> +    {
> +      ptr->_errno = EOVERFLOW;
> +      return EOF;
> +    }
>    f._flags = __SWR | __SSTR;
>    f._bf._base = f._p = (unsigned char *) str;
>    f._bf._size = f._w = (size > 0 ? size - 1 : 0);
>    f._file = -1;  /* No file. */
>    ret = _vfprintf_r (ptr, &f, fmt, ap);
> +  if (ret < EOF)
> +    ptr->_errno = EOVERFLOW;
>    if (size > 0)
>      *f._p = 0;
>    return ret;
> Index: libc/stdio/wbuf.c
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio/wbuf.c,v
> retrieving revision 1.6
> diff -u -r1.6 wbuf.c
> --- libc/stdio/wbuf.c	26 Sep 2006 21:22:19 -0000	1.6
> +++ libc/stdio/wbuf.c	13 Mar 2007 23:05:09 -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
> @@ -53,7 +53,7 @@
>     */
>  
>    fp->_w = fp->_lbfsize;
> -  if (cantwrite (fp))
> +  if (cantwrite (ptr, fp))
>      {
>        fp->_flags |= __SERR;
>        ptr->_errno = EBADF;
> 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 23:05:09 -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
> @@ -29,7 +29,8 @@
>   */
>  
>  int
> -_DEFUN(__swsetup, (fp),
> +_DEFUN(__swsetup_r, (ptr, fp),
> +       struct _reent *ptr _AND
>         register FILE * fp)
>  {
>    /* Make sure stdio is set up.  */
> @@ -48,7 +49,7 @@
>  	{
>  	  /* clobber any ungetc data */
>  	  if (HASUB (fp))
> -	    FREEUB (fp);
> +	    FREEUB (ptr, fp);
>  	  fp->_flags &= ~(__SRD | __SEOF);
>  	  fp->_r = 0;
>  	  fp->_p = fp->_bf._base;
> @@ -63,7 +64,7 @@
>     */
>    if (fp->_bf._base == NULL 
>          && (!(fp->_flags & __SSTR) || (fp->_flags & __SMBF)))
> -    __smakebuf (fp);
> +    __smakebuf_r (ptr, fp);
>  
>    if (fp->_flags & __SLBF)
>      {
> @@ -78,5 +79,5 @@
>    else
>      fp->_w = fp->_flags & __SNBF ? 0 : fp->_bf._size;
>  
> -  return 0;
> +  return (!fp->_bf._base && (fp->_flags & __SMBF)) ? EOF : 0;
>  }
> 
> 



More information about the Newlib mailing list