!908 [sync] PR-892: sync from glibc upstream branch 2.38
From: @openeuler-sync-bot Reviewed-by: @liqingqing_1229 Signed-off-by: @liqingqing_1229
This commit is contained in:
commit
30fa876e88
147
Make-tst-ungetc-use-libsupport.patch
Normal file
147
Make-tst-ungetc-use-libsupport.patch
Normal file
@ -0,0 +1,147 @@
|
||||
From 87a1968a72e4b4e5436f3e2be1ed8a8d5a5862c7 Mon Sep 17 00:00:00 2001
|
||||
From: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Wed, 14 Aug 2024 19:20:04 -0400
|
||||
Subject: [PATCH] Make tst-ungetc use libsupport
|
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
(cherry picked from commit 3f7df7e757f4efec38e45d4068e5492efcac4856)
|
||||
---
|
||||
stdio-common/tst-ungetc.c | 112 +++++++++++++++++++-------------------
|
||||
1 file changed, 57 insertions(+), 55 deletions(-)
|
||||
|
||||
diff --git a/stdio-common/tst-ungetc.c b/stdio-common/tst-ungetc.c
|
||||
index 1344b2b591..5c808f0734 100644
|
||||
--- a/stdio-common/tst-ungetc.c
|
||||
+++ b/stdio-common/tst-ungetc.c
|
||||
@@ -1,70 +1,72 @@
|
||||
-/* Test for ungetc bugs. */
|
||||
+/* Test for ungetc bugs.
|
||||
+ Copyright (C) 1996-2024 Free Software Foundation, Inc.
|
||||
+ Copyright The GNU Toolchain Authors.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
-#include <unistd.h>
|
||||
-
|
||||
-#undef assert
|
||||
-#define assert(x) \
|
||||
- if (!(x)) \
|
||||
- { \
|
||||
- fputs ("test failed: " #x "\n", stderr); \
|
||||
- retval = 1; \
|
||||
- goto the_end; \
|
||||
- }
|
||||
+#include <support/check.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/temp_file.h>
|
||||
+#include <support/xstdio.h>
|
||||
+#include <support/xunistd.h>
|
||||
|
||||
-int
|
||||
-main (int argc, char *argv[])
|
||||
+static int
|
||||
+do_test (void)
|
||||
{
|
||||
- char name[] = "/tmp/tst-ungetc.XXXXXX";
|
||||
+ char *name = NULL;
|
||||
FILE *fp = NULL;
|
||||
- int retval = 0;
|
||||
int c;
|
||||
char buffer[64];
|
||||
|
||||
- int fd = mkstemp (name);
|
||||
+ int fd = create_temp_file ("tst-ungetc.", &name);
|
||||
if (fd == -1)
|
||||
- {
|
||||
- printf ("mkstemp failed: %m\n");
|
||||
- return 1;
|
||||
- }
|
||||
- close (fd);
|
||||
- fp = fopen (name, "w");
|
||||
- assert (fp != NULL)
|
||||
- fputs ("bla", fp);
|
||||
- fclose (fp);
|
||||
- fp = NULL;
|
||||
+ FAIL_EXIT1 ("cannot create temporary file: %m");
|
||||
+ xclose (fd);
|
||||
|
||||
- fp = fopen (name, "r");
|
||||
- assert (fp != NULL);
|
||||
- assert (ungetc ('z', fp) == 'z');
|
||||
- assert (getc (fp) == 'z');
|
||||
- assert (getc (fp) == 'b');
|
||||
- assert (getc (fp) == 'l');
|
||||
- assert (ungetc ('m', fp) == 'm');
|
||||
- assert (getc (fp) == 'm');
|
||||
- assert ((c = getc (fp)) == 'a');
|
||||
- assert (getc (fp) == EOF);
|
||||
- assert (ungetc (c, fp) == c);
|
||||
- assert (feof (fp) == 0);
|
||||
- assert (getc (fp) == c);
|
||||
- assert (getc (fp) == EOF);
|
||||
- fclose (fp);
|
||||
- fp = NULL;
|
||||
+ fp = xfopen (name, "w");
|
||||
+ fputs ("bla", fp);
|
||||
+ xfclose (fp);
|
||||
|
||||
- fp = fopen (name, "r");
|
||||
- assert (fp != NULL);
|
||||
- assert (getc (fp) == 'b');
|
||||
- assert (getc (fp) == 'l');
|
||||
- assert (ungetc ('b', fp) == 'b');
|
||||
- assert (fread (buffer, 1, 64, fp) == 2);
|
||||
- assert (buffer[0] == 'b');
|
||||
- assert (buffer[1] == 'a');
|
||||
+ fp = xfopen (name, "r");
|
||||
+ TEST_VERIFY_EXIT (ungetc ('z', fp) == 'z');
|
||||
+ TEST_VERIFY_EXIT (getc (fp) == 'z');
|
||||
+ TEST_VERIFY_EXIT (getc (fp) == 'b');
|
||||
+ TEST_VERIFY_EXIT (getc (fp) == 'l');
|
||||
+ TEST_VERIFY_EXIT (ungetc ('m', fp) == 'm');
|
||||
+ TEST_VERIFY_EXIT (getc (fp) == 'm');
|
||||
+ TEST_VERIFY_EXIT ((c = getc (fp)) == 'a');
|
||||
+ TEST_VERIFY_EXIT (getc (fp) == EOF);
|
||||
+ TEST_VERIFY_EXIT (ungetc (c, fp) == c);
|
||||
+ TEST_VERIFY_EXIT (feof (fp) == 0);
|
||||
+ TEST_VERIFY_EXIT (getc (fp) == c);
|
||||
+ TEST_VERIFY_EXIT (getc (fp) == EOF);
|
||||
+ xfclose (fp);
|
||||
|
||||
-the_end:
|
||||
- if (fp != NULL)
|
||||
- fclose (fp);
|
||||
- unlink (name);
|
||||
+ fp = xfopen (name, "r");
|
||||
+ TEST_VERIFY_EXIT (getc (fp) == 'b');
|
||||
+ TEST_VERIFY_EXIT (getc (fp) == 'l');
|
||||
+ TEST_VERIFY_EXIT (ungetc ('b', fp) == 'b');
|
||||
+ TEST_VERIFY_EXIT (fread (buffer, 1, 64, fp) == 2);
|
||||
+ TEST_VERIFY_EXIT (buffer[0] == 'b');
|
||||
+ TEST_VERIFY_EXIT (buffer[1] == 'a');
|
||||
+ xfclose (fp);
|
||||
|
||||
- return retval;
|
||||
+ return 0;
|
||||
}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
--
|
||||
2.33.0
|
||||
|
||||
18
glibc.spec
18
glibc.spec
@ -67,7 +67,7 @@
|
||||
##############################################################################
|
||||
Name: glibc
|
||||
Version: 2.38
|
||||
Release: 37
|
||||
Release: 38
|
||||
Summary: The GNU libc libraries
|
||||
License: %{all_license}
|
||||
URL: http://www.gnu.org/software/glibc/
|
||||
@ -215,6 +215,13 @@ Patch125: 0012-resolv-Fix-tst-resolv-short-response-for-older-GCC-b.patch
|
||||
Patch126: Fix-name-space-violation-in-fortify-wrappers-bug-320.patch
|
||||
Patch127: x86-Fix-bug-in-strchrnul-evex512-BZ-32078.patch
|
||||
Patch128: 19614-locale-Handle-loading-a-missing-locale-twice-Bug-14.patch
|
||||
Patch129: support-Add-FAIL-test-failure-helper.patch
|
||||
Patch130: stdio-common-Add-test-for-vfscanf-with-matches-longe.patch
|
||||
Patch131: Make-tst-ungetc-use-libsupport.patch
|
||||
Patch132: ungetc-Fix-uninitialized-read-when-putting-into-unus.patch
|
||||
Patch133: ungetc-Fix-backup-buffer-leak-on-program-exit-BZ-278.patch
|
||||
Patch134: posix-Use-support-check.h-facilities-in-tst-truncate.patch
|
||||
Patch135: nptl-Use-support-check.h-facilities-in-tst-setuid3.patch
|
||||
|
||||
#openEuler patch list
|
||||
Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch
|
||||
@ -1447,6 +1454,15 @@ fi
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Mon Sep 9 2024 Qingqing Li <liqingqing3@huawei.com> - 2.38-38
|
||||
- nptl: Use <support/check.h> facilities in tst-setuid3
|
||||
- posix: Use <support/check.h> facilities in tst-truncate and tst-truncate64
|
||||
- ungetc: Fix backup buffer leak on program exit [BZ #27821]
|
||||
- ungetc: Fix uninitialized read when putting into unused streams [BZ #27821]
|
||||
- Make tst-ungetc use libsupport
|
||||
- stdio-common: Add test for vfscanf with matches longer than INT_MAX [BZ #27650]
|
||||
- support: Add FAIL test failure helper
|
||||
|
||||
* Wed Sep 4 2024 Zhaoshuang <zhaoshuang@uniontech.com> - 2.38-37
|
||||
- Fix issue that loading a missing locale twice [BZ #14247]
|
||||
|
||||
|
||||
134
nptl-Use-support-check.h-facilities-in-tst-setuid3.patch
Normal file
134
nptl-Use-support-check.h-facilities-in-tst-setuid3.patch
Normal file
@ -0,0 +1,134 @@
|
||||
From f30501ca7557a194a53af22ff5b47b3189c48216 Mon Sep 17 00:00:00 2001
|
||||
From: "Maciej W. Rozycki" <macro@redhat.com>
|
||||
Date: Fri, 26 Jul 2024 13:21:34 +0100
|
||||
Subject: [PATCH] nptl: Use <support/check.h> facilities in tst-setuid3
|
||||
|
||||
Remove local FAIL macro in favor to FAIL_EXIT1 from <support/check.h>,
|
||||
which provides equivalent reporting, with the name of the file and the
|
||||
line number within of the failure site additionally included. Remove
|
||||
FAIL_ERR altogether and include ": %m" explicitly with the format string
|
||||
supplied to FAIL_EXIT1 as there seems little value to have a separate
|
||||
macro just for this.
|
||||
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
(cherry picked from commit 8c98195af6e6f1ce21743fc26c723e0f7e45bcf2)
|
||||
---
|
||||
sysdeps/pthread/tst-setuid3.c | 37 +++++++++++++++--------------------
|
||||
1 file changed, 16 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/sysdeps/pthread/tst-setuid3.c b/sysdeps/pthread/tst-setuid3.c
|
||||
index 58b78d3116..d13848a647 100644
|
||||
--- a/sysdeps/pthread/tst-setuid3.c
|
||||
+++ b/sysdeps/pthread/tst-setuid3.c
|
||||
@@ -15,24 +15,19 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
-#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
|
||||
+#include <support/check.h>
|
||||
+
|
||||
/* The test must run under a non-privileged user ID. */
|
||||
static const uid_t test_uid = 1;
|
||||
|
||||
static pthread_barrier_t barrier1;
|
||||
static pthread_barrier_t barrier2;
|
||||
|
||||
-#define FAIL(fmt, ...) \
|
||||
- do { printf ("FAIL: " fmt "\n", __VA_ARGS__); _exit (1); } while (0)
|
||||
-
|
||||
-#define FAIL_ERR(fmt, ...) \
|
||||
- do { printf ("FAIL: " fmt ": %m\n", __VA_ARGS__); _exit (1); } while (0)
|
||||
-
|
||||
/* True if x is not a successful return code from pthread_barrier_wait. */
|
||||
static inline bool
|
||||
is_invalid_barrier_ret (int x)
|
||||
@@ -45,10 +40,10 @@ thread_func (void *ctx __attribute__ ((unused)))
|
||||
{
|
||||
int ret = pthread_barrier_wait (&barrier1);
|
||||
if (is_invalid_barrier_ret (ret))
|
||||
- FAIL ("pthread_barrier_wait (barrier1) (on thread): %d", ret);
|
||||
+ FAIL_EXIT1 ("pthread_barrier_wait (barrier1) (on thread): %d", ret);
|
||||
ret = pthread_barrier_wait (&barrier2);
|
||||
if (is_invalid_barrier_ret (ret))
|
||||
- FAIL ("pthread_barrier_wait (barrier2) (on thread): %d", ret);
|
||||
+ FAIL_EXIT1 ("pthread_barrier_wait (barrier2) (on thread): %d", ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -59,13 +54,13 @@ setuid_failure (int phase)
|
||||
switch (ret)
|
||||
{
|
||||
case 0:
|
||||
- FAIL ("setuid succeeded unexpectedly in phase %d", phase);
|
||||
+ FAIL_EXIT1 ("setuid succeeded unexpectedly in phase %d", phase);
|
||||
case -1:
|
||||
if (errno != EPERM)
|
||||
- FAIL_ERR ("setuid phase %d", phase);
|
||||
+ FAIL_EXIT1 ("setuid phase %d: %m", phase);
|
||||
break;
|
||||
default:
|
||||
- FAIL ("invalid setuid return value in phase %d: %d", phase, ret);
|
||||
+ FAIL_EXIT1 ("invalid setuid return value in phase %d: %d", phase, ret);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,42 +69,42 @@ do_test (void)
|
||||
{
|
||||
if (getuid () == 0)
|
||||
if (setuid (test_uid) != 0)
|
||||
- FAIL_ERR ("setuid (%u)", (unsigned) test_uid);
|
||||
+ FAIL_EXIT1 ("setuid (%u): %m", (unsigned) test_uid);
|
||||
if (setuid (getuid ()))
|
||||
- FAIL_ERR ("setuid (%s)", "getuid ()");
|
||||
+ FAIL_EXIT1 ("setuid (%s): %m", "getuid ()");
|
||||
setuid_failure (1);
|
||||
|
||||
int ret = pthread_barrier_init (&barrier1, NULL, 2);
|
||||
if (ret != 0)
|
||||
- FAIL ("pthread_barrier_init (barrier1): %d", ret);
|
||||
+ FAIL_EXIT1 ("pthread_barrier_init (barrier1): %d", ret);
|
||||
ret = pthread_barrier_init (&barrier2, NULL, 2);
|
||||
if (ret != 0)
|
||||
- FAIL ("pthread_barrier_init (barrier2): %d", ret);
|
||||
+ FAIL_EXIT1 ("pthread_barrier_init (barrier2): %d", ret);
|
||||
|
||||
pthread_t thread;
|
||||
ret = pthread_create (&thread, NULL, thread_func, NULL);
|
||||
if (ret != 0)
|
||||
- FAIL ("pthread_create: %d", ret);
|
||||
+ FAIL_EXIT1 ("pthread_create: %d", ret);
|
||||
|
||||
/* Ensure that the thread is running properly. */
|
||||
ret = pthread_barrier_wait (&barrier1);
|
||||
if (is_invalid_barrier_ret (ret))
|
||||
- FAIL ("pthread_barrier_wait (barrier1): %d", ret);
|
||||
+ FAIL_EXIT1 ("pthread_barrier_wait (barrier1): %d", ret);
|
||||
|
||||
setuid_failure (2);
|
||||
|
||||
/* Check success case. */
|
||||
if (setuid (getuid ()) != 0)
|
||||
- FAIL_ERR ("setuid (%s)", "getuid ()");
|
||||
+ FAIL_EXIT1 ("setuid (%s): %m", "getuid ()");
|
||||
|
||||
/* Shutdown. */
|
||||
ret = pthread_barrier_wait (&barrier2);
|
||||
if (is_invalid_barrier_ret (ret))
|
||||
- FAIL ("pthread_barrier_wait (barrier2): %d", ret);
|
||||
+ FAIL_EXIT1 ("pthread_barrier_wait (barrier2): %d", ret);
|
||||
|
||||
ret = pthread_join (thread, NULL);
|
||||
if (ret != 0)
|
||||
- FAIL ("pthread_join: %d", ret);
|
||||
+ FAIL_EXIT1 ("pthread_join: %d", ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
--
|
||||
2.33.0
|
||||
|
||||
89
posix-Use-support-check.h-facilities-in-tst-truncate.patch
Normal file
89
posix-Use-support-check.h-facilities-in-tst-truncate.patch
Normal file
@ -0,0 +1,89 @@
|
||||
From 15ca66303f7a7ce463bb41a83d88474996e46efd Mon Sep 17 00:00:00 2001
|
||||
From: "Maciej W. Rozycki" <macro@redhat.com>
|
||||
Date: Fri, 26 Jul 2024 13:21:34 +0100
|
||||
Subject: [PATCH] posix: Use <support/check.h> facilities in tst-truncate
|
||||
and tst-truncate64
|
||||
|
||||
Remove local FAIL macro in favor to FAIL_RET from <support/check.h>,
|
||||
which provides equivalent reporting, with the name of the file of the
|
||||
failure site additionally included, for the tst-truncate-common core
|
||||
shared between the tst-truncate and tst-truncate64 tests.
|
||||
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
(cherry picked from commit fe47595504a55e7bb992f8928533df154b510383)
|
||||
---
|
||||
posix/tst-truncate-common.c | 25 ++++++++++++-------------
|
||||
1 file changed, 12 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/posix/tst-truncate-common.c b/posix/tst-truncate-common.c
|
||||
index 9a8163fdfe..fd32eb73c5 100644
|
||||
--- a/posix/tst-truncate-common.c
|
||||
+++ b/posix/tst-truncate-common.c
|
||||
@@ -21,6 +21,8 @@
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
+#include <support/check.h>
|
||||
+
|
||||
static void do_prepare (void);
|
||||
#define PREPARE(argc, argv) do_prepare ()
|
||||
static int do_test (void);
|
||||
@@ -42,9 +44,6 @@ do_prepare (void)
|
||||
}
|
||||
}
|
||||
|
||||
-#define FAIL(str) \
|
||||
- do { printf ("error: %s (line %d)\n", str, __LINE__); return 1; } while (0)
|
||||
-
|
||||
static int
|
||||
do_test_with_offset (off_t offset)
|
||||
{
|
||||
@@ -54,35 +53,35 @@ do_test_with_offset (off_t offset)
|
||||
memset (buf, 0xcf, sizeof (buf));
|
||||
|
||||
if (pwrite (temp_fd, buf, sizeof (buf), offset) != sizeof (buf))
|
||||
- FAIL ("write failed");
|
||||
+ FAIL_RET ("write failed");
|
||||
if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + sizeof (buf)))
|
||||
- FAIL ("initial size wrong");
|
||||
+ FAIL_RET ("initial size wrong");
|
||||
|
||||
if (ftruncate (temp_fd, offset + 800) < 0)
|
||||
- FAIL ("size reduction with ftruncate failed");
|
||||
+ FAIL_RET ("size reduction with ftruncate failed");
|
||||
if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 800))
|
||||
- FAIL ("size after reduction with ftruncate is incorrect");
|
||||
+ FAIL_RET ("size after reduction with ftruncate is incorrect");
|
||||
|
||||
/* The following test covers more than POSIX. POSIX does not require
|
||||
that ftruncate() can increase the file size. But we are testing
|
||||
Unix systems. */
|
||||
if (ftruncate (temp_fd, offset + 1200) < 0)
|
||||
- FAIL ("size increate with ftruncate failed");
|
||||
+ FAIL_RET ("size increate with ftruncate failed");
|
||||
if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 1200))
|
||||
- FAIL ("size after increase is incorrect");
|
||||
+ FAIL_RET ("size after increase is incorrect");
|
||||
|
||||
if (truncate (temp_filename, offset + 800) < 0)
|
||||
- FAIL ("size reduction with truncate failed");
|
||||
+ FAIL_RET ("size reduction with truncate failed");
|
||||
if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 800))
|
||||
- FAIL ("size after reduction with truncate incorrect");
|
||||
+ FAIL_RET ("size after reduction with truncate incorrect");
|
||||
|
||||
/* The following test covers more than POSIX. POSIX does not require
|
||||
that truncate() can increase the file size. But we are testing
|
||||
Unix systems. */
|
||||
if (truncate (temp_filename, (offset + 1200)) < 0)
|
||||
- FAIL ("size increase with truncate failed");
|
||||
+ FAIL_RET ("size increase with truncate failed");
|
||||
if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 1200))
|
||||
- FAIL ("size increase with truncate is incorrect");
|
||||
+ FAIL_RET ("size increase with truncate is incorrect");
|
||||
|
||||
return 0;
|
||||
}
|
||||
--
|
||||
2.33.0
|
||||
|
||||
176
stdio-common-Add-test-for-vfscanf-with-matches-longe.patch
Normal file
176
stdio-common-Add-test-for-vfscanf-with-matches-longe.patch
Normal file
@ -0,0 +1,176 @@
|
||||
From 99ffa84bdcdc3d81e82f448279f0c8278dd30964 Mon Sep 17 00:00:00 2001
|
||||
From: "Maciej W. Rozycki" <macro@redhat.com>
|
||||
Date: Fri, 26 Jul 2024 13:21:34 +0100
|
||||
Subject: [PATCH] stdio-common: Add test for vfscanf with matches longer
|
||||
than INT_MAX [BZ #27650]
|
||||
|
||||
Complement commit b03e4d7bd25b ("stdio: fix vfscanf with matches longer
|
||||
than INT_MAX (bug 27650)") and add a test case for the issue, inspired
|
||||
by the reproducer provided with the bug report.
|
||||
|
||||
This has been verified to succeed as from the commit referred and fail
|
||||
beforehand.
|
||||
|
||||
As the test requires 2GiB of data to be passed around its performance
|
||||
has been evaluated using a choice of systems and the execution time
|
||||
determined to be respectively in the range of 9s for POWER9@2.166GHz,
|
||||
24s for FU740@1.2GHz, and 40s for 74Kf@950MHz. As this is on the verge
|
||||
of and beyond the default timeout it has been increased by the factor of
|
||||
8. Regardless, following recent practice the test has been added to the
|
||||
standard rather than extended set.
|
||||
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
(cherry picked from commit 89cddc8a7096f3d9225868304d2bc0a1aaf07d63)
|
||||
---
|
||||
stdio-common/Makefile | 5 ++
|
||||
stdio-common/tst-scanf-bz27650.c | 108 +++++++++++++++++++++++++++++++
|
||||
2 files changed, 113 insertions(+)
|
||||
create mode 100644 stdio-common/tst-scanf-bz27650.c
|
||||
|
||||
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
|
||||
index 3866362bae..2bcbaf754a 100644
|
||||
--- a/stdio-common/Makefile
|
||||
+++ b/stdio-common/Makefile
|
||||
@@ -243,6 +243,7 @@ tests := \
|
||||
tst-scanf-binary-c2x \
|
||||
tst-scanf-binary-gnu11 \
|
||||
tst-scanf-binary-gnu89 \
|
||||
+ tst-scanf-bz27650 \
|
||||
tst-scanf-round \
|
||||
tst-scanf-to_inpunct \
|
||||
tst-setvbuf1 \
|
||||
@@ -312,6 +313,7 @@ generated += \
|
||||
tst-printf-fp-free.mtrace \
|
||||
tst-printf-fp-leak-mem.out \
|
||||
tst-printf-fp-leak.mtrace \
|
||||
+ tst-scanf-bz27650.mtrace \
|
||||
tst-vfprintf-width-prec-mem.out \
|
||||
tst-vfprintf-width-prec.mtrace \
|
||||
# generated
|
||||
@@ -398,6 +400,9 @@ tst-printf-fp-free-ENV = \
|
||||
tst-printf-fp-leak-ENV = \
|
||||
MALLOC_TRACE=$(objpfx)tst-printf-fp-leak.mtrace \
|
||||
LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
|
||||
+tst-scanf-bz27650-ENV = \
|
||||
+ MALLOC_TRACE=$(objpfx)tst-scanf-bz27650.mtrace \
|
||||
+ LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
|
||||
|
||||
$(objpfx)tst-unbputc.out: tst-unbputc.sh $(objpfx)tst-unbputc
|
||||
$(SHELL) $< $(common-objpfx) '$(test-program-prefix)'; \
|
||||
diff --git a/stdio-common/tst-scanf-bz27650.c b/stdio-common/tst-scanf-bz27650.c
|
||||
new file mode 100644
|
||||
index 0000000000..3a742bc865
|
||||
--- /dev/null
|
||||
+++ b/stdio-common/tst-scanf-bz27650.c
|
||||
@@ -0,0 +1,108 @@
|
||||
+/* Test for BZ #27650, formatted input matching beyond INT_MAX.
|
||||
+ Copyright (C) 2024 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <error.h>
|
||||
+#include <errno.h>
|
||||
+#include <limits.h>
|
||||
+#include <mcheck.h>
|
||||
+#include <stddef.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+#include <sys/types.h>
|
||||
+
|
||||
+#include <support/check.h>
|
||||
+#include <support/test-driver.h>
|
||||
+
|
||||
+/* Produce a stream of more than INT_MAX characters via buffer BUF of
|
||||
+ size SIZE according to bookkeeping in COOKIE and then return EOF. */
|
||||
+
|
||||
+static ssize_t
|
||||
+io_read (void *cookie, char *buf, size_t size)
|
||||
+{
|
||||
+ unsigned int *written = cookie;
|
||||
+ unsigned int w = *written;
|
||||
+
|
||||
+ if (w > INT_MAX)
|
||||
+ return 0;
|
||||
+
|
||||
+ memset (buf, 'a', size);
|
||||
+ *written = w + size;
|
||||
+ return size;
|
||||
+}
|
||||
+
|
||||
+/* Consume a stream of more than INT_MAX characters from an artificial
|
||||
+ input stream of which none is the new line character. The call to
|
||||
+ fscanf is supposed to complete upon the EOF condition of input,
|
||||
+ however in the presence of BZ #27650 it will terminate prematurely
|
||||
+ with characters still outstanding in input. Diagnose the condition
|
||||
+ and return status accordingly. */
|
||||
+
|
||||
+int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ static cookie_io_functions_t io_funcs = { .read = io_read };
|
||||
+ unsigned int written = 0;
|
||||
+ FILE *in;
|
||||
+ int v;
|
||||
+
|
||||
+ mtrace ();
|
||||
+
|
||||
+ in = fopencookie (&written, "r", io_funcs);
|
||||
+ if (in == NULL)
|
||||
+ {
|
||||
+ FAIL ("fopencookie: %m");
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ v = fscanf (in, "%*[^\n]");
|
||||
+ if (ferror (in))
|
||||
+ {
|
||||
+ FAIL ("fscanf: input failure, at %u: %m", written);
|
||||
+ goto out_close;
|
||||
+ }
|
||||
+ else if (v == EOF)
|
||||
+ {
|
||||
+ FAIL ("fscanf: unexpected end of file, at %u", written);
|
||||
+ goto out_close;
|
||||
+ }
|
||||
+
|
||||
+ if (!feof (in))
|
||||
+ {
|
||||
+ v = fgetc (in);
|
||||
+ if (ferror (in))
|
||||
+ FAIL ("fgetc: input failure: %m");
|
||||
+ else if (v == EOF)
|
||||
+ FAIL ("fgetc: unexpected end of file after missing end of file");
|
||||
+ else if (v == '\n')
|
||||
+ FAIL ("unexpected new line character received");
|
||||
+ else
|
||||
+ FAIL ("character received after end of file expected: \\x%02x", v);
|
||||
+ }
|
||||
+
|
||||
+out_close:
|
||||
+ if (fclose (in) != 0)
|
||||
+ FAIL ("fclose: %m");
|
||||
+
|
||||
+out:
|
||||
+ return EXIT_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+#define TIMEOUT (DEFAULT_TIMEOUT * 8)
|
||||
+#include <support/test-driver.c>
|
||||
--
|
||||
2.33.0
|
||||
|
||||
201
support-Add-FAIL-test-failure-helper.patch
Normal file
201
support-Add-FAIL-test-failure-helper.patch
Normal file
@ -0,0 +1,201 @@
|
||||
From 28f358bc4209ab0425170cdccf65bb1fe861148f Mon Sep 17 00:00:00 2001
|
||||
From: "Maciej W. Rozycki" <macro@redhat.com>
|
||||
Date: Fri, 26 Jul 2024 13:21:34 +0100
|
||||
Subject: [PATCH] support: Add FAIL test failure helper
|
||||
|
||||
Add a FAIL test failure helper analogous to FAIL_RET, that does not
|
||||
cause the current function to return, providing a standardized way to
|
||||
report a test failure with a message supplied while permitting the
|
||||
caller to continue executing, for further reporting, cleaning up, etc.
|
||||
|
||||
Update existing test cases that provide a conflicting definition of FAIL
|
||||
by removing the local FAIL definition and then as follows:
|
||||
|
||||
- tst-fortify-syslog: provide a meaningful message in addition to the
|
||||
file name already added by <support/check.h>; 'support_record_failure'
|
||||
is already called by 'support_print_failure_impl' invoked by the new
|
||||
FAIL test failure helper.
|
||||
|
||||
- tst-ctype: no update to FAIL calls required, with the name of the file
|
||||
and the line number within of the failure site additionally included
|
||||
by the new FAIL test failure helper, and error counting plus count
|
||||
reporting upon test program termination also already provided by
|
||||
'support_record_failure' and 'support_report_failure' respectively,
|
||||
called by 'support_print_failure_impl' and 'adjust_exit_status' also
|
||||
respectively. However in a number of places 'printf' is called and
|
||||
the error count adjusted by hand, so update these places to make use
|
||||
of FAIL instead. And last but not least adjust the final summary just
|
||||
to report completion, with any error count following as reported by
|
||||
the test driver.
|
||||
|
||||
- test-tgmath2: no update to FAIL calls required, with the name of the
|
||||
file of the failure site additionally included by the new FAIL test
|
||||
failure helper. Also there is no need to track the return status by
|
||||
hand as any call to FAIL will eventually cause the test case to return
|
||||
an unsuccesful exit status regardless of the return status from the
|
||||
test function, via a call to 'adjust_exit_status' made by the test
|
||||
driver.
|
||||
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
(cherry picked from commit 1b97a9f23bf605ca608162089c94187573fb2a9e)
|
||||
---
|
||||
localedata/tst-ctype.c | 40 +++++++++-------------------------------
|
||||
math/test-tgmath2.c | 13 +++----------
|
||||
support/check.h | 5 +++++
|
||||
3 files changed, 17 insertions(+), 41 deletions(-)
|
||||
|
||||
diff --git a/localedata/tst-ctype.c b/localedata/tst-ctype.c
|
||||
index 098bf51335..355b666866 100644
|
||||
--- a/localedata/tst-ctype.c
|
||||
+++ b/localedata/tst-ctype.c
|
||||
@@ -21,6 +21,8 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
+#include <support/check.h>
|
||||
+
|
||||
|
||||
static const char lower[] = "abcdefghijklmnopqrstuvwxyz";
|
||||
static const char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
@@ -53,19 +55,11 @@ static struct classes
|
||||
#define nclasses (sizeof (classes) / sizeof (classes[0]))
|
||||
|
||||
|
||||
-#define FAIL(str, args...) \
|
||||
- { \
|
||||
- printf (" " str "\n", ##args); \
|
||||
- ++errors; \
|
||||
- }
|
||||
-
|
||||
-
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
const char *cp;
|
||||
const char *cp2;
|
||||
- int errors = 0;
|
||||
char *inpline = NULL;
|
||||
size_t inplinelen = 0;
|
||||
char *resline = NULL;
|
||||
@@ -394,11 +388,8 @@ punct = %04x alnum = %04x\n",
|
||||
{
|
||||
if (((__ctype_b[(unsigned int) *inp] & classes[n].mask) != 0)
|
||||
!= (*resp != '0'))
|
||||
- {
|
||||
- printf (" is%s('%c' = '\\x%02x') %s true\n", inpline,
|
||||
- *inp, *inp, *resp == '1' ? "not" : "is");
|
||||
- ++errors;
|
||||
- }
|
||||
+ FAIL (" is%s('%c' = '\\x%02x') %s true\n", inpline,
|
||||
+ *inp, *inp, *resp == '1' ? "not" : "is");
|
||||
++inp;
|
||||
++resp;
|
||||
}
|
||||
@@ -408,11 +399,8 @@ punct = %04x alnum = %04x\n",
|
||||
while (*inp != '\0')
|
||||
{
|
||||
if (tolower (*inp) != *resp)
|
||||
- {
|
||||
- printf (" tolower('%c' = '\\x%02x') != '%c'\n",
|
||||
- *inp, *inp, *resp);
|
||||
- ++errors;
|
||||
- }
|
||||
+ FAIL (" tolower('%c' = '\\x%02x') != '%c'\n",
|
||||
+ *inp, *inp, *resp);
|
||||
++inp;
|
||||
++resp;
|
||||
}
|
||||
@@ -422,11 +410,8 @@ punct = %04x alnum = %04x\n",
|
||||
while (*inp != '\0')
|
||||
{
|
||||
if (toupper (*inp) != *resp)
|
||||
- {
|
||||
- printf (" toupper('%c' = '\\x%02x') != '%c'\n",
|
||||
- *inp, *inp, *resp);
|
||||
- ++errors;
|
||||
- }
|
||||
+ FAIL (" toupper('%c' = '\\x%02x') != '%c'\n",
|
||||
+ *inp, *inp, *resp);
|
||||
++inp;
|
||||
++resp;
|
||||
}
|
||||
@@ -436,14 +421,7 @@ punct = %04x alnum = %04x\n",
|
||||
}
|
||||
|
||||
|
||||
- if (errors != 0)
|
||||
- {
|
||||
- printf (" %d error%s for `%s' locale\n\n\n", errors,
|
||||
- errors == 1 ? "" : "s", setlocale (LC_ALL, NULL));
|
||||
- return 1;
|
||||
- }
|
||||
-
|
||||
- printf (" No errors for `%s' locale\n\n\n", setlocale (LC_ALL, NULL));
|
||||
+ printf ("Completed testing for `%s' locale\n\n\n", setlocale (LC_ALL, NULL));
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/math/test-tgmath2.c b/math/test-tgmath2.c
|
||||
index 6dd0d64da5..deba439e0c 100644
|
||||
--- a/math/test-tgmath2.c
|
||||
+++ b/math/test-tgmath2.c
|
||||
@@ -24,6 +24,8 @@
|
||||
#include <string.h>
|
||||
#include <tgmath.h>
|
||||
|
||||
+#include <support/check.h>
|
||||
+
|
||||
//#define DEBUG
|
||||
|
||||
typedef complex float cfloat;
|
||||
@@ -87,13 +89,6 @@ enum
|
||||
int count;
|
||||
int counts[Tlast][C_last];
|
||||
|
||||
-#define FAIL(str) \
|
||||
- do \
|
||||
- { \
|
||||
- printf ("%s failure on line %d\n", (str), __LINE__); \
|
||||
- result = 1; \
|
||||
- } \
|
||||
- while (0)
|
||||
#define TEST_TYPE_ONLY(expr, rettype) \
|
||||
do \
|
||||
{ \
|
||||
@@ -133,8 +128,6 @@ int counts[Tlast][C_last];
|
||||
int
|
||||
test_cos (const int Vint4, const long long int Vllong4)
|
||||
{
|
||||
- int result = 0;
|
||||
-
|
||||
TEST (cos (vfloat1), float, cos);
|
||||
TEST (cos (vdouble1), double, cos);
|
||||
TEST (cos (vldouble1), ldouble, cos);
|
||||
@@ -152,7 +145,7 @@ test_cos (const int Vint4, const long long int Vllong4)
|
||||
TEST (cos (Vcdouble1), cdouble, cos);
|
||||
TEST (cos (Vcldouble1), cldouble, cos);
|
||||
|
||||
- return result;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
int
|
||||
diff --git a/support/check.h b/support/check.h
|
||||
index e6ae39f1a1..0a9fff484f 100644
|
||||
--- a/support/check.h
|
||||
+++ b/support/check.h
|
||||
@@ -24,6 +24,11 @@
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
+/* Record a test failure, print the failure message to standard output
|
||||
+ and pass the result of 1 through. */
|
||||
+#define FAIL(...) \
|
||||
+ support_print_failure_impl (__FILE__, __LINE__, __VA_ARGS__)
|
||||
+
|
||||
/* Record a test failure, print the failure message to standard output
|
||||
and return 1. */
|
||||
#define FAIL_RET(...) \
|
||||
--
|
||||
2.33.0
|
||||
|
||||
145
ungetc-Fix-backup-buffer-leak-on-program-exit-BZ-278.patch
Normal file
145
ungetc-Fix-backup-buffer-leak-on-program-exit-BZ-278.patch
Normal file
@ -0,0 +1,145 @@
|
||||
From b9f72bd5de931eac39219018c2fa319a449bb2cf Mon Sep 17 00:00:00 2001
|
||||
From: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Tue, 13 Aug 2024 21:08:49 -0400
|
||||
Subject: [PATCH] ungetc: Fix backup buffer leak on program exit [BZ
|
||||
#27821]
|
||||
|
||||
If a file descriptor is left unclosed and is cleaned up by _IO_cleanup
|
||||
on exit, its backup buffer remains unfreed, registering as a leak in
|
||||
valgrind. This is not strictly an issue since (1) the program should
|
||||
ideally be closing the stream once it's not in use and (2) the program
|
||||
is about to exit anyway, so keeping the backup buffer around a wee bit
|
||||
longer isn't a real problem. Free it anyway to keep valgrind happy
|
||||
when the streams in question are the standard ones, i.e. stdout, stdin
|
||||
or stderr.
|
||||
|
||||
Also, the _IO_have_backup macro checks for _IO_save_base,
|
||||
which is a roundabout way to check for a backup buffer instead of
|
||||
directly looking for _IO_backup_base. The roundabout check breaks when
|
||||
the main get area has not been used and user pushes a char into the
|
||||
backup buffer with ungetc. Fix this to use the _IO_backup_base
|
||||
directly.
|
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
(cherry picked from commit 3e1d8d1d1dca24ae90df2ea826a8916896fc7e77)
|
||||
---
|
||||
libio/genops.c | 6 ++++++
|
||||
libio/libioP.h | 4 ++--
|
||||
stdio-common/Makefile | 7 +++++++
|
||||
stdio-common/tst-ungetc-leak.c | 32 ++++++++++++++++++++++++++++++++
|
||||
4 files changed, 47 insertions(+), 2 deletions(-)
|
||||
create mode 100644 stdio-common/tst-ungetc-leak.c
|
||||
|
||||
diff --git a/libio/genops.c b/libio/genops.c
|
||||
index c673c0acec..fb06245467 100644
|
||||
--- a/libio/genops.c
|
||||
+++ b/libio/genops.c
|
||||
@@ -789,6 +789,12 @@ _IO_unbuffer_all (void)
|
||||
legacy = 1;
|
||||
#endif
|
||||
|
||||
+ /* Free up the backup area if it was ever allocated. */
|
||||
+ if (_IO_have_backup (fp))
|
||||
+ _IO_free_backup_area (fp);
|
||||
+ if (fp->_mode > 0 && _IO_have_wbackup (fp))
|
||||
+ _IO_free_wbackup_area (fp);
|
||||
+
|
||||
if (! (fp->_flags & _IO_UNBUFFERED)
|
||||
/* Iff stream is un-orientated, it wasn't used. */
|
||||
&& (legacy || fp->_mode != 0))
|
||||
diff --git a/libio/libioP.h b/libio/libioP.h
|
||||
index 745278e076..e75ee770bc 100644
|
||||
--- a/libio/libioP.h
|
||||
+++ b/libio/libioP.h
|
||||
@@ -577,8 +577,8 @@ extern void _IO_old_init (FILE *fp, int flags) __THROW;
|
||||
((__fp)->_wide_data->_IO_write_base \
|
||||
= (__fp)->_wide_data->_IO_write_ptr = __p, \
|
||||
(__fp)->_wide_data->_IO_write_end = (__ep))
|
||||
-#define _IO_have_backup(fp) ((fp)->_IO_save_base != NULL)
|
||||
-#define _IO_have_wbackup(fp) ((fp)->_wide_data->_IO_save_base != NULL)
|
||||
+#define _IO_have_backup(fp) ((fp)->_IO_backup_base != NULL)
|
||||
+#define _IO_have_wbackup(fp) ((fp)->_wide_data->_IO_backup_base != NULL)
|
||||
#define _IO_in_backup(fp) ((fp)->_flags & _IO_IN_BACKUP)
|
||||
#define _IO_have_markers(fp) ((fp)->_markers != NULL)
|
||||
#define _IO_blen(fp) ((fp)->_IO_buf_end - (fp)->_IO_buf_base)
|
||||
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
|
||||
index 2bcbaf754a..381040570b 100644
|
||||
--- a/stdio-common/Makefile
|
||||
+++ b/stdio-common/Makefile
|
||||
@@ -256,6 +256,7 @@ tests := \
|
||||
tst-swscanf \
|
||||
tst-tmpnam \
|
||||
tst-ungetc \
|
||||
+ tst-ungetc-leak \
|
||||
tst-unlockedio \
|
||||
tst-vfprintf-mbs-prec \
|
||||
tst-vfprintf-user-type \
|
||||
@@ -300,6 +301,7 @@ tests-special += \
|
||||
$(objpfx)tst-printfsz-islongdouble.out \
|
||||
$(objpfx)tst-setvbuf1-cmp.out \
|
||||
$(objpfx)tst-unbputc.out \
|
||||
+ $(objpfx)tst-ungetc-leak-mem.out \
|
||||
$(objpfx)tst-vfprintf-width-prec-mem.out \
|
||||
# tests-special
|
||||
|
||||
@@ -314,6 +316,8 @@ generated += \
|
||||
tst-printf-fp-leak-mem.out \
|
||||
tst-printf-fp-leak.mtrace \
|
||||
tst-scanf-bz27650.mtrace \
|
||||
+ tst-ungetc-leak-mem.out \
|
||||
+ tst-ungetc-leak.mtrace \
|
||||
tst-vfprintf-width-prec-mem.out \
|
||||
tst-vfprintf-width-prec.mtrace \
|
||||
# generated
|
||||
@@ -403,6 +407,9 @@ tst-printf-fp-leak-ENV = \
|
||||
tst-scanf-bz27650-ENV = \
|
||||
MALLOC_TRACE=$(objpfx)tst-scanf-bz27650.mtrace \
|
||||
LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
|
||||
+tst-ungetc-leak-ENV = \
|
||||
+ MALLOC_TRACE=$(objpfx)tst-ungetc-leak.mtrace \
|
||||
+ LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
|
||||
|
||||
$(objpfx)tst-unbputc.out: tst-unbputc.sh $(objpfx)tst-unbputc
|
||||
$(SHELL) $< $(common-objpfx) '$(test-program-prefix)'; \
|
||||
diff --git a/stdio-common/tst-ungetc-leak.c b/stdio-common/tst-ungetc-leak.c
|
||||
new file mode 100644
|
||||
index 0000000000..6c5152b43f
|
||||
--- /dev/null
|
||||
+++ b/stdio-common/tst-ungetc-leak.c
|
||||
@@ -0,0 +1,32 @@
|
||||
+/* Test for memory leak with ungetc when stream is unused.
|
||||
+ Copyright The GNU Toolchain Authors.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <mcheck.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/support.h>
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ mtrace ();
|
||||
+ TEST_COMPARE (ungetc('y', stdin), 'y');
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
--
|
||||
2.33.0
|
||||
|
||||
78
ungetc-Fix-uninitialized-read-when-putting-into-unus.patch
Normal file
78
ungetc-Fix-uninitialized-read-when-putting-into-unus.patch
Normal file
@ -0,0 +1,78 @@
|
||||
From 804d3c8db79db204154dcf5e11a76f14fdddc570 Mon Sep 17 00:00:00 2001
|
||||
From: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Tue, 13 Aug 2024 21:00:06 -0400
|
||||
Subject: [PATCH] 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)
|
||||
---
|
||||
libio/genops.c | 2 +-
|
||||
manual/stdio.texi | 8 +++-----
|
||||
stdio-common/tst-ungetc.c | 2 ++
|
||||
3 files changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/libio/genops.c b/libio/genops.c
|
||||
index fbd8dd9e75..c673c0acec 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 9cf622403f..a54cd369db 100644
|
||||
--- a/manual/stdio.texi
|
||||
+++ b/manual/stdio.texi
|
||||
@@ -1474,11 +1474,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 5c808f0734..388b202493 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);
|
||||
--
|
||||
2.33.0
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user