This is the mail archive of the newlib@sourceware.org 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]

Re: *printf_r and reentrancy


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;
}





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