You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
71 lines
3.2 KiB
71 lines
3.2 KiB
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);
|
|
|