newlib: libc: Fix crash on fprintf to a wide-oriented stream.
Previously, fprintf() on a wide-oriented stream crashes or outputs garbage. This is because a narrow char string which can be odd bytes in length is cast into a wide char string which should be even bytes in length in __sprint_r/__sfputs_r based on the __SWID flag. As a result, if the length is odd bytes, the reading buffer runs over the buffer length, which causes a crash. If the length is even bytes, garbage is printed. With this patch, any output to the stream which is set to different orientation fails with error just like glibc. Note that it behaves differently from other libc implementations such as BSD, musl and Solaris. Reviewed-by: Corinna Vinschen <corinna@vinschen.de> Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
This commit is contained in:
parent
7863c07a92
commit
3d94e07c49
|
@ -177,7 +177,9 @@ _fgetwc_r (struct _reent *ptr,
|
||||||
wint_t r;
|
wint_t r;
|
||||||
|
|
||||||
_newlib_flockfile_start (fp);
|
_newlib_flockfile_start (fp);
|
||||||
ORIENT(fp, 1);
|
if (ORIENT(fp, 1) != 1)
|
||||||
|
r = WEOF;
|
||||||
|
else
|
||||||
r = __fgetwc (ptr, fp);
|
r = __fgetwc (ptr, fp);
|
||||||
_newlib_flockfile_end (fp);
|
_newlib_flockfile_end (fp);
|
||||||
return r;
|
return r;
|
||||||
|
|
|
@ -33,7 +33,8 @@ wint_t
|
||||||
_fgetwc_unlocked_r (struct _reent *ptr,
|
_fgetwc_unlocked_r (struct _reent *ptr,
|
||||||
register FILE *fp)
|
register FILE *fp)
|
||||||
{
|
{
|
||||||
ORIENT(fp, 1);
|
if (ORIENT(fp, 1) != 1)
|
||||||
|
return WEOF;
|
||||||
return __fgetwc (ptr, fp);
|
return __fgetwc (ptr, fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,7 +110,8 @@ _fgetws_r (struct _reent *ptr,
|
||||||
unsigned char *nl;
|
unsigned char *nl;
|
||||||
|
|
||||||
_newlib_flockfile_start (fp);
|
_newlib_flockfile_start (fp);
|
||||||
ORIENT (fp, 1);
|
if (ORIENT (fp, 1) != 1)
|
||||||
|
goto error;
|
||||||
|
|
||||||
if (n <= 0)
|
if (n <= 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -103,7 +103,9 @@ _fputs_r (struct _reent * ptr,
|
||||||
CHECK_INIT(ptr, fp);
|
CHECK_INIT(ptr, fp);
|
||||||
|
|
||||||
_newlib_flockfile_start (fp);
|
_newlib_flockfile_start (fp);
|
||||||
ORIENT (fp, -1);
|
if (ORIENT (fp, -1) != -1)
|
||||||
|
result = EOF;
|
||||||
|
else
|
||||||
result = __sfvwrite_r (ptr, fp, &uio);
|
result = __sfvwrite_r (ptr, fp, &uio);
|
||||||
_newlib_flockfile_end (fp);
|
_newlib_flockfile_end (fp);
|
||||||
return result;
|
return result;
|
||||||
|
@ -113,7 +115,8 @@ _fputs_r (struct _reent * ptr,
|
||||||
CHECK_INIT(ptr, fp);
|
CHECK_INIT(ptr, fp);
|
||||||
|
|
||||||
_newlib_flockfile_start (fp);
|
_newlib_flockfile_start (fp);
|
||||||
ORIENT (fp, -1);
|
if (ORIENT (fp, -1) != -1)
|
||||||
|
goto error;
|
||||||
/* Make sure we can write. */
|
/* Make sure we can write. */
|
||||||
if (cantwrite (ptr, fp))
|
if (cantwrite (ptr, fp))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
|
@ -169,7 +169,9 @@ _fputwc_r (struct _reent *ptr,
|
||||||
wint_t r;
|
wint_t r;
|
||||||
|
|
||||||
_newlib_flockfile_start (fp);
|
_newlib_flockfile_start (fp);
|
||||||
ORIENT(fp, 1);
|
if (ORIENT(fp, 1) != 1)
|
||||||
|
r = WEOF;
|
||||||
|
else
|
||||||
r = __fputwc(ptr, wc, fp);
|
r = __fputwc(ptr, wc, fp);
|
||||||
_newlib_flockfile_end (fp);
|
_newlib_flockfile_end (fp);
|
||||||
return r;
|
return r;
|
||||||
|
|
|
@ -34,7 +34,8 @@ _fputwc_unlocked_r (struct _reent *ptr,
|
||||||
wchar_t wc,
|
wchar_t wc,
|
||||||
FILE *fp)
|
FILE *fp)
|
||||||
{
|
{
|
||||||
ORIENT(fp, 1);
|
if (ORIENT(fp, 1) != 1)
|
||||||
|
return WEOF;
|
||||||
return __fputwc(ptr, wc, fp);
|
return __fputwc(ptr, wc, fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -105,7 +105,8 @@ _fputws_r (struct _reent *ptr,
|
||||||
struct __siov iov;
|
struct __siov iov;
|
||||||
|
|
||||||
_newlib_flockfile_start (fp);
|
_newlib_flockfile_start (fp);
|
||||||
ORIENT (fp, 1);
|
if (ORIENT (fp, 1) != 1)
|
||||||
|
goto error;
|
||||||
if (cantwrite (ptr, fp) != 0)
|
if (cantwrite (ptr, fp) != 0)
|
||||||
goto error;
|
goto error;
|
||||||
uio.uio_iov = &iov;
|
uio.uio_iov = &iov;
|
||||||
|
@ -129,7 +130,8 @@ error:
|
||||||
return (-1);
|
return (-1);
|
||||||
#else
|
#else
|
||||||
_newlib_flockfile_start (fp);
|
_newlib_flockfile_start (fp);
|
||||||
ORIENT (fp, 1);
|
if (ORIENT (fp, 1) != 1)
|
||||||
|
goto error;
|
||||||
if (cantwrite (ptr, fp) != 0)
|
if (cantwrite (ptr, fp) != 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
|
|
@ -158,7 +158,11 @@ _fread_r (struct _reent * ptr,
|
||||||
CHECK_INIT(ptr, fp);
|
CHECK_INIT(ptr, fp);
|
||||||
|
|
||||||
_newlib_flockfile_start (fp);
|
_newlib_flockfile_start (fp);
|
||||||
ORIENT (fp, -1);
|
if (ORIENT (fp, -1) != -1)
|
||||||
|
{
|
||||||
|
count = 0;
|
||||||
|
goto ret;
|
||||||
|
}
|
||||||
if (fp->_r < 0)
|
if (fp->_r < 0)
|
||||||
fp->_r = 0;
|
fp->_r = 0;
|
||||||
total = resid;
|
total = resid;
|
||||||
|
@ -252,6 +256,7 @@ _fread_r (struct _reent * ptr,
|
||||||
return crlf_r(ptr, fp, buf, total, 0) / size;
|
return crlf_r(ptr, fp, buf, total, 0) / size;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
ret:
|
||||||
_newlib_flockfile_end (fp);
|
_newlib_flockfile_end (fp);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,7 +133,11 @@ _fwrite_r (struct _reent * ptr,
|
||||||
CHECK_INIT(ptr, fp);
|
CHECK_INIT(ptr, fp);
|
||||||
|
|
||||||
_newlib_flockfile_start (fp);
|
_newlib_flockfile_start (fp);
|
||||||
ORIENT (fp, -1);
|
if (ORIENT (fp, -1) != -1)
|
||||||
|
{
|
||||||
|
_newlib_flockfile_exit (fp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (__sfvwrite_r (ptr, fp, &uio) == 0)
|
if (__sfvwrite_r (ptr, fp, &uio) == 0)
|
||||||
{
|
{
|
||||||
_newlib_flockfile_exit (fp);
|
_newlib_flockfile_exit (fp);
|
||||||
|
@ -148,7 +152,8 @@ _fwrite_r (struct _reent * ptr,
|
||||||
CHECK_INIT (ptr, fp);
|
CHECK_INIT (ptr, fp);
|
||||||
|
|
||||||
_newlib_flockfile_start (fp);
|
_newlib_flockfile_start (fp);
|
||||||
ORIENT (fp, -1);
|
if (ORIENT (fp, -1) != -1)
|
||||||
|
goto ret;
|
||||||
/* Make sure we can write. */
|
/* Make sure we can write. */
|
||||||
if (cantwrite (ptr, fp))
|
if (cantwrite (ptr, fp))
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
|
@ -232,20 +232,23 @@ extern _READ_WRITE_RETURN_TYPE __swrite64 (struct _reent *, void *,
|
||||||
* orientation. If o < 0, the stream has byte-orientation.
|
* orientation. If o < 0, the stream has byte-orientation.
|
||||||
*/
|
*/
|
||||||
#define ORIENT(fp,ori) \
|
#define ORIENT(fp,ori) \
|
||||||
do \
|
( \
|
||||||
{ \
|
( \
|
||||||
if (!((fp)->_flags & __SORD)) \
|
((fp)->_flags & __SORD) ? \
|
||||||
{ \
|
0 \
|
||||||
(fp)->_flags |= __SORD; \
|
: \
|
||||||
if (ori > 0) \
|
( \
|
||||||
(fp)->_flags2 |= __SWID; \
|
((fp)->_flags |= __SORD), \
|
||||||
else \
|
(ori > 0) ? \
|
||||||
(fp)->_flags2 &= ~__SWID; \
|
((fp)->_flags2 |= __SWID) \
|
||||||
} \
|
: \
|
||||||
} \
|
((fp)->_flags2 &= ~__SWID) \
|
||||||
while (0)
|
) \
|
||||||
|
), \
|
||||||
|
((fp)->_flags2 & __SWID) ? 1 : -1 \
|
||||||
|
)
|
||||||
#else
|
#else
|
||||||
#define ORIENT(fp,ori)
|
#define ORIENT(fp,ori) (-1)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* WARNING: _dcvt is defined in the stdlib directory, not here! */
|
/* WARNING: _dcvt is defined in the stdlib directory, not here! */
|
||||||
|
|
|
@ -84,6 +84,8 @@ _putc_r (struct _reent *ptr,
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
CHECK_INIT (ptr, fp);
|
CHECK_INIT (ptr, fp);
|
||||||
|
if (ORIENT (fp, -1) != -1)
|
||||||
|
return EOF;
|
||||||
_newlib_flockfile_start (fp);
|
_newlib_flockfile_start (fp);
|
||||||
result = __sputc_r (ptr, c, fp);
|
result = __sputc_r (ptr, c, fp);
|
||||||
_newlib_flockfile_end (fp);
|
_newlib_flockfile_end (fp);
|
||||||
|
@ -100,6 +102,8 @@ putc (int c,
|
||||||
struct _reent *reent = _REENT;
|
struct _reent *reent = _REENT;
|
||||||
|
|
||||||
CHECK_INIT (reent, fp);
|
CHECK_INIT (reent, fp);
|
||||||
|
if (ORIENT (fp, -1) != -1)
|
||||||
|
return EOF;
|
||||||
_newlib_flockfile_start (fp);
|
_newlib_flockfile_start (fp);
|
||||||
result = __sputc_r (reent, c, fp);
|
result = __sputc_r (reent, c, fp);
|
||||||
_newlib_flockfile_end (fp);
|
_newlib_flockfile_end (fp);
|
||||||
|
|
|
@ -87,7 +87,9 @@ _puts_r (struct _reent *ptr,
|
||||||
fp = _stdout_r (ptr);
|
fp = _stdout_r (ptr);
|
||||||
CHECK_INIT (ptr, fp);
|
CHECK_INIT (ptr, fp);
|
||||||
_newlib_flockfile_start (fp);
|
_newlib_flockfile_start (fp);
|
||||||
ORIENT (fp, -1);
|
if (ORIENT (fp, -1) != -1)
|
||||||
|
result = EOF;
|
||||||
|
else
|
||||||
result = (__sfvwrite_r (ptr, fp, &uio) ? EOF : '\n');
|
result = (__sfvwrite_r (ptr, fp, &uio) ? EOF : '\n');
|
||||||
_newlib_flockfile_end (fp);
|
_newlib_flockfile_end (fp);
|
||||||
return result;
|
return result;
|
||||||
|
@ -100,7 +102,8 @@ _puts_r (struct _reent *ptr,
|
||||||
fp = _stdout_r (ptr);
|
fp = _stdout_r (ptr);
|
||||||
CHECK_INIT (ptr, fp);
|
CHECK_INIT (ptr, fp);
|
||||||
_newlib_flockfile_start (fp);
|
_newlib_flockfile_start (fp);
|
||||||
ORIENT (fp, -1);
|
if (ORIENT (fp, -1) != -1)
|
||||||
|
goto err;
|
||||||
/* Make sure we can write. */
|
/* Make sure we can write. */
|
||||||
if (cantwrite (ptr, fp))
|
if (cantwrite (ptr, fp))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
|
@ -43,7 +43,8 @@ __srefill_r (struct _reent * ptr,
|
||||||
|
|
||||||
CHECK_INIT (ptr, fp);
|
CHECK_INIT (ptr, fp);
|
||||||
|
|
||||||
ORIENT (fp, -1);
|
if (ORIENT (fp, -1) != -1)
|
||||||
|
return EOF;
|
||||||
|
|
||||||
fp->_r = 0; /* largely a convenience for callers */
|
fp->_r = 0; /* largely a convenience for callers */
|
||||||
|
|
||||||
|
|
|
@ -125,7 +125,11 @@ _ungetc_r (struct _reent *rptr,
|
||||||
|
|
||||||
_newlib_flockfile_start (fp);
|
_newlib_flockfile_start (fp);
|
||||||
|
|
||||||
ORIENT (fp, -1);
|
if (ORIENT (fp, -1) != -1)
|
||||||
|
{
|
||||||
|
_newlib_flockfile_exit (fp);
|
||||||
|
return EOF;
|
||||||
|
}
|
||||||
|
|
||||||
/* After ungetc, we won't be at eof anymore */
|
/* After ungetc, we won't be at eof anymore */
|
||||||
fp->_flags &= ~__SEOF;
|
fp->_flags &= ~__SEOF;
|
||||||
|
|
|
@ -82,8 +82,9 @@ _ungetwc_r (struct _reent *ptr,
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
_newlib_flockfile_start (fp);
|
_newlib_flockfile_start (fp);
|
||||||
ORIENT (fp, 1);
|
if (ORIENT (fp, 1) != 1)
|
||||||
if (wc == WEOF)
|
wc = WEOF;
|
||||||
|
else if (wc == WEOF)
|
||||||
wc = WEOF;
|
wc = WEOF;
|
||||||
else if ((len = _wcrtomb_r(ptr, buf, wc, &fp->_mbstate)) == (size_t)-1)
|
else if ((len = _wcrtomb_r(ptr, buf, wc, &fp->_mbstate)) == (size_t)-1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -845,7 +845,10 @@ _VFPRINTF_R (struct _reent *data,
|
||||||
CHECK_INIT (data, fp);
|
CHECK_INIT (data, fp);
|
||||||
_newlib_flockfile_start (fp);
|
_newlib_flockfile_start (fp);
|
||||||
|
|
||||||
ORIENT(fp, -1);
|
if (ORIENT(fp, -1) != -1) {
|
||||||
|
_newlib_flockfile_exit (fp);
|
||||||
|
return (EOF);
|
||||||
|
}
|
||||||
|
|
||||||
/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
|
/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
|
||||||
if (cantwrite (data, fp)) {
|
if (cantwrite (data, fp)) {
|
||||||
|
|
|
@ -589,7 +589,11 @@ __SVFSCANF_R (struct _reent *rptr,
|
||||||
|
|
||||||
_newlib_flockfile_start (fp);
|
_newlib_flockfile_start (fp);
|
||||||
|
|
||||||
ORIENT (fp, -1);
|
if (ORIENT (fp, -1) != -1)
|
||||||
|
{
|
||||||
|
nassigned = EOF;
|
||||||
|
goto all_done;
|
||||||
|
}
|
||||||
|
|
||||||
nassigned = 0;
|
nassigned = 0;
|
||||||
nread = 0;
|
nread = 0;
|
||||||
|
|
|
@ -588,7 +588,10 @@ _VFWPRINTF_R (struct _reent *data,
|
||||||
CHECK_INIT (data, fp);
|
CHECK_INIT (data, fp);
|
||||||
_newlib_flockfile_start (fp);
|
_newlib_flockfile_start (fp);
|
||||||
|
|
||||||
ORIENT(fp, 1);
|
if (ORIENT(fp, 1) != 1) {
|
||||||
|
_newlib_flockfile_exit (fp);
|
||||||
|
return (EOF);
|
||||||
|
}
|
||||||
|
|
||||||
/* sorry, fwprintf(read_only_file, "") returns EOF, not 0 */
|
/* sorry, fwprintf(read_only_file, "") returns EOF, not 0 */
|
||||||
if (cantwrite (data, fp)) {
|
if (cantwrite (data, fp)) {
|
||||||
|
|
|
@ -516,7 +516,11 @@ __SVFWSCANF_R (struct _reent *rptr,
|
||||||
|
|
||||||
_newlib_flockfile_start (fp);
|
_newlib_flockfile_start (fp);
|
||||||
|
|
||||||
ORIENT (fp, 1);
|
if (ORIENT (fp, 1) != 1)
|
||||||
|
{
|
||||||
|
nassigned = EOF;
|
||||||
|
goto all_done;
|
||||||
|
}
|
||||||
|
|
||||||
nassigned = 0;
|
nassigned = 0;
|
||||||
nread = 0;
|
nread = 0;
|
||||||
|
|
Loading…
Reference in New Issue