]> sourceware.org Git - glibc.git/commitdiff
ungetc: Fix uninitialized read when putting into unused streams [BZ #27821]
authorSiddhesh Poyarekar <siddhesh@sourceware.org>
Wed, 14 Aug 2024 01:00:06 +0000 (21:00 -0400)
committerSiddhesh Poyarekar <siddhesh@sourceware.org>
Thu, 15 Aug 2024 17:55:07 +0000 (13:55 -0400)
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>
libio/genops.c
manual/stdio.texi
stdio-common/tst-ungetc.c

index 99f5e80f20c2bac8f395d2377ec069cb999a0339..b012fa33d2a5cc054f8405fad2b95cd6c8e3355c 100644 (file)
@@ -662,7 +662,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--;
index 0db4e090af09f641bd8a402c41ca54ac967226a8..29888a361f1d356fac83817fb587c1c3f1c52fbb 100644 (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
index 5c808f073419f00b246dd362829ec3aea3e4aef0..388b202493ddd586b93870faec6e4be3a55c9b41 100644 (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);
This page took 0.046929 seconds and 5 git commands to generate.