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]

[PATCH] Fix potential reent issue


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Quoting from the comments in include/reent.h:

Dynamic reentrancy is specified by the __DYNAMIC_REENT__ flag.  This
flag denotes setting up a macro to replace _REENT with a function call
to __getreent().

And in fact, the definition of _REENT in include/sys/reent.h is

#if defined(__DYNAMIC_REENT__) && !defined(__SINGLE_THREAD__)
[...]
# define _REENT (__getreent())
#else
# define _REENT _impure_ptr
#endif

However, this works only if the rest of newlib never uses _impure_ptr
directly. A quick grep on the sources found two uses of _impure_ptr, one
in the definition of stdin, stdout, stderr in stdio.h, and one in the
definition of getwchar/putwchar in wchar.h.

These uses occur only if _REENT_ONLY is defined. So, my understanding is
that if both __DYNAMIC_REENT__ and _REENT_ONLY are defined, those direct
uses of _impure_ptr leak out the wrong reentrancy structure.

I'm also wondering why these even exist when _REENT_ONLY is defined,
shouldn't one use only _stdin_r, _stdout_r, _stderr_r, _getwchar_r and
_putwchar_r in this case, according to the rule that non _r functions
aren't defined when _REENT_ONLY is? Anyway, these are visible in public
headers, so users may well have used those.

Attached is a patch that implements them by calling __getreent() if both
__DYNAMIC_REENT__ and _REENT_ONLY are defined. Note that this came out
of a code review, I don't have such a setup to test this change, so
please look at the patch carefully.

newlib/ChangeLog
2013-06-23  Terraneo Federico  <fede.tft@hotmail.it>

	* libc/include/stdio.h (stdin): Use __getreent when required
          (stdout): Ditto
	  (stderr): Ditto
        * libc/include/wchar.h (getwchar): Ditto
          (putwchar): Ditto
        * libc/include/sys/reent.h: Make __getreent available even if
          _REENT_ONLY is defined.


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQEcBAEBAgAGBQJRxtivAAoJECkLFtN5Xr9fHC4H/29YzTexscZv2Ez96b/UWexG
kBqyL80OSLiJXX3Vi4B+YqvRS4dANVMXihXu5LCGp/zoqpBk+gpFrBEuwwPtxWyr
mmwBAZ3OV9DlA2YwCbqWbrs2RPHzSaTG6JT0xRCUiIyDK0INPuTgnApj29Lq6A+B
GZeVhOPjRGWMglx1G6oaQYpmYU7bn04TGsRR5GfY6O38ih3fDx8yhW9/pjKP+uFg
jCieTQhv8ETZMaDxhuO/ldMCPokclEC2MNEGnYJ5moP8YYrt3utgrmp/6gVLkl0g
v3NmpmQ2xU89n8gLdYhrkFaSX6Ut+/XuLXdydZf3x1+hut35BspY64NHRPxgcZc=
=wANw
-----END PGP SIGNATURE-----
diff -ruN a/newlib/libc/include/stdio.h b/newlib/libc/include/stdio.h
--- a/newlib/libc/include/stdio.h	2012-11-01 12:51:11.000000000 +0100
+++ b/newlib/libc/include/stdio.h	2013-06-23 11:36:41.607057328 +0200
@@ -144,9 +144,15 @@
 #define	stdout	(_REENT->_stdout)
 #define	stderr	(_REENT->_stderr)
 #else /* _REENT_ONLY */
+#if defined(__DYNAMIC_REENT__) && !defined(__SINGLE_THREAD__)
+#define	stdin	(__getreent()->_stdin)
+#define	stdout	(__getreent()->_stdout)
+#define	stderr	(__getreent()->_stderr)
+#else /* defined(__DYNAMIC_REENT__) && !defined(__SINGLE_THREAD__) */
 #define	stdin	(_impure_ptr->_stdin)
 #define	stdout	(_impure_ptr->_stdout)
 #define	stderr	(_impure_ptr->_stderr)
+#endif /* defined(__DYNAMIC_REENT__) && !defined(__SINGLE_THREAD__) */
 #endif /* _REENT_ONLY */
 
 #define _stdin_r(x)	((x)->_stdin)
diff -ruN a/newlib/libc/include/sys/reent.h b/newlib/libc/include/sys/reent.h
--- a/newlib/libc/include/sys/reent.h	2013-05-09 01:13:51.000000000 +0200
+++ b/newlib/libc/include/sys/reent.h	2013-06-23 11:36:41.607057328 +0200
@@ -795,14 +795,15 @@
 
 void _reclaim_reent _PARAMS ((struct _reent *));
 
+#if defined(__DYNAMIC_REENT__) && !defined(__SINGLE_THREAD__) && !defined(__getreent)
+struct _reent * _EXFUN(__getreent, (void));
+#endif
+
 /* #define _REENT_ONLY define this to get only reentrant routines */
 
 #ifndef _REENT_ONLY
 
 #if defined(__DYNAMIC_REENT__) && !defined(__SINGLE_THREAD__)
-#ifndef __getreent
-  struct _reent * _EXFUN(__getreent, (void));
-#endif
 # define _REENT (__getreent())
 #else /* __SINGLE_THREAD__ || !__DYNAMIC_REENT__ */
 # define _REENT _impure_ptr
diff -ruN a/newlib/libc/include/wchar.h b/newlib/libc/include/wchar.h
--- a/newlib/libc/include/wchar.h	2012-11-01 12:51:11.000000000 +0100
+++ b/newlib/libc/include/wchar.h	2013-06-23 11:36:41.615057863 +0200
@@ -182,10 +182,15 @@
 #ifndef _REENT_ONLY
 #define getwchar()	fgetwc(_REENT->_stdin)
 #define putwchar(wc)	fputwc((wc), _REENT->_stdout)
-#else
+#else /* _REENT_ONLY */
+#if defined(__DYNAMIC_REENT__) && !defined(__SINGLE_THREAD__)
+#define getwchar()	fgetwc(__getreent()->_stdin)
+#define putwchar(wc)	fputwc((wc), __getreent()->_stdout)
+#else /* defined(__DYNAMIC_REENT__) && !defined(__SINGLE_THREAD__) */
 #define getwchar()	fgetwc(_impure_ptr->_stdin)
 #define putwchar(wc)	fputwc((wc), _impure_ptr->_stdout)
-#endif
+#endif /* defined(__DYNAMIC_REENT__) && !defined(__SINGLE_THREAD__) */
+#endif /* _REENT_ONLY */
 
 _END_STD_C
 

Attachment: dynamic_reent.patch.sig
Description: Binary data


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