1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-30 22:43:12 +03:00

libio: do not attempt to free wide buffers of legacy streams [BZ #24228]

Commit a601b74d31 aka glibc-2.23~693
("In preparation for fixing BZ#16734, fix failure in misc/tst-error1-mem
when _G_HAVE_MMAP is turned off.") introduced a regression:
_IO_unbuffer_all now invokes _IO_wsetb to free wide buffers of all
files, including legacy standard files which are small statically
allocated objects that do not have wide buffers and the _mode member,
causing memory corruption.

Another memory corruption in _IO_unbuffer_all happens when -1
is assigned to the _mode member of legacy standard files that
do not have it.

[BZ #24228]
* libio/genops.c (_IO_unbuffer_all)
[SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)]: Do not attempt to free wide
buffers and access _IO_FILE_complete members of legacy libio streams.
* libio/tst-bz24228.c: New file.
* libio/tst-bz24228.map: Likewise.
* libio/Makefile [build-shared] (tests): Add tst-bz24228.
[build-shared] (generated): Add tst-bz24228.mtrace and
tst-bz24228.check.
[run-built-tests && build-shared] (tests-special): Add
$(objpfx)tst-bz24228-mem.out.
(LDFLAGS-tst-bz24228, tst-bz24228-ENV): New variables.
($(objpfx)tst-bz24228-mem.out): New rule.
This commit is contained in:
Dmitry V. Levin
2019-02-13 01:20:51 +00:00
parent 49bc41b642
commit 21cc130b78
5 changed files with 76 additions and 5 deletions

View File

@ -789,9 +789,16 @@ _IO_unbuffer_all (void)
for (fp = (FILE *) _IO_list_all; fp; fp = fp->_chain)
{
int legacy = 0;
#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
if (__glibc_unlikely (_IO_vtable_offset (fp) != 0))
legacy = 1;
#endif
if (! (fp->_flags & _IO_UNBUFFERED)
/* Iff stream is un-orientated, it wasn't used. */
&& fp->_mode != 0)
&& (legacy || fp->_mode != 0))
{
#ifdef _IO_MTSAFE_IO
int cnt;
@ -805,7 +812,7 @@ _IO_unbuffer_all (void)
__sched_yield ();
#endif
if (! dealloc_buffers && !(fp->_flags & _IO_USER_BUF))
if (! legacy && ! dealloc_buffers && !(fp->_flags & _IO_USER_BUF))
{
fp->_flags |= _IO_USER_BUF;
@ -816,7 +823,7 @@ _IO_unbuffer_all (void)
_IO_SETBUF (fp, NULL, 0);
if (fp->_mode > 0)
if (! legacy && fp->_mode > 0)
_IO_wsetb (fp, NULL, NULL, 0);
#ifdef _IO_MTSAFE_IO
@ -827,7 +834,8 @@ _IO_unbuffer_all (void)
/* Make sure that never again the wide char functions can be
used. */
fp->_mode = -1;
if (! legacy)
fp->_mode = -1;
}
#ifdef _IO_MTSAFE_IO