ungetc: Fix uninitialized read when putting into unused streams [BZ #27821]

When ungetc is called on an unused stream, the backup buffer is
allocated without the main get area being present.  This results in
every subsequent ungetc (as the stream remains in the backup area)
checking uninitialized memory in the backup buffer when trying to put a
character back into the stream.

Avoid comparing the input character with buffer contents when in backup
to avoid this uninitialized read.  The uninitialized read is harmless in
this context since the location is promptly overwritten with the input
character, thus fulfilling ungetc functionality.

Also adjust wording in the manual to drop the paragraph that says glibc
cannot do multiple ungetc back to back since with this change, ungetc
can actually do this.

Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit cdf0f88f97)
This commit is contained in:
Siddhesh Poyarekar 2024-08-13 21:00:06 -04:00
parent f0c308ab23
commit 70939528c6
3 changed files with 6 additions and 6 deletions

View File

@ -635,7 +635,7 @@ _IO_sputbackc (FILE *fp, int c)
{
int result;
if (fp->_IO_read_ptr > fp->_IO_read_base
if (fp->_IO_read_ptr > fp->_IO_read_base && !_IO_in_backup (fp)
&& (unsigned char)fp->_IO_read_ptr[-1] == (unsigned char)c)
{
fp->_IO_read_ptr--;

View File

@ -1467,11 +1467,9 @@ program; usually @code{ungetc} is used only to unread a character that
was just read from the same stream. @Theglibc{} supports this
even on files opened in binary mode, but other systems might not.
@Theglibc{} only supports one character of pushback---in other
words, it does not work to call @code{ungetc} twice without doing input
in between. Other systems might let you push back multiple characters;
then reading from the stream retrieves the characters in the reverse
order that they were pushed.
@Theglibc{} supports pushing back multiple characters; subsequently
reading from the stream retrieves the characters in the reverse order
that they were pushed.
Pushing back characters doesn't alter the file; only the internal
buffering for the stream is affected. If a file positioning function

View File

@ -48,6 +48,8 @@ do_test (void)
TEST_VERIFY_EXIT (getc (fp) == 'b');
TEST_VERIFY_EXIT (getc (fp) == 'l');
TEST_VERIFY_EXIT (ungetc ('m', fp) == 'm');
TEST_VERIFY_EXIT (ungetc ('n', fp) == 'n');
TEST_VERIFY_EXIT (getc (fp) == 'n');
TEST_VERIFY_EXIT (getc (fp) == 'm');
TEST_VERIFY_EXIT ((c = getc (fp)) == 'a');
TEST_VERIFY_EXIT (getc (fp) == EOF);