72 lines
3.2 KiB
Diff
72 lines
3.2 KiB
Diff
|
commit 01a731da41a6d47cdd6b90f0da1d89dd8cf2b9cd
|
||
|
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||
|
Date: Tue Aug 13 21:00:06 2024 -0400
|
||
|
|
||
|
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 cdf0f88f97b0aaceb894cc02b21159d148d7065c)
|
||
|
(cherry picked from commit 804d3c8db79db204154dcf5e11a76f14fdddc570)
|
||
|
|
||
|
diff --git a/libio/genops.c b/libio/genops.c
|
||
|
index fa509f6219abaf23..a5dd6a06d9e259d8 100644
|
||
|
--- a/libio/genops.c
|
||
|
+++ b/libio/genops.c
|
||
|
@@ -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--;
|
||
|
diff --git a/manual/stdio.texi b/manual/stdio.texi
|
||
|
index d3d855fc62b8768b..60ab7e7a5d505bb6 100644
|
||
|
--- a/manual/stdio.texi
|
||
|
+++ b/manual/stdio.texi
|
||
|
@@ -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
|
||
|
diff --git a/stdio-common/tst-ungetc.c b/stdio-common/tst-ungetc.c
|
||
|
index 5c808f073419f00b..388b202493ddd586 100644
|
||
|
--- a/stdio-common/tst-ungetc.c
|
||
|
+++ b/stdio-common/tst-ungetc.c
|
||
|
@@ -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);
|