2a30b8f4b2
Upstream commit: dcaf51b41e259387602774829c45222d0507f90a - elf: Change ldconfig auxcache magic number (bug 32231) - Make tst-strtod-underflow type-generic - Add crt1-2.0.o for glibc 2.0 compatibility tests - Add tests of more strtod special cases - Add more tests of strtod end pointer - Make tst-strtod2 and tst-strtod5 type-generic - powerpc64le: Build new strtod tests with long double ABI flags (bug 32145) - Do not set errno for overflowing NaN payload in strtod/nan (bug 32045) - Improve NaN payload testing - Make __strtod_internal tests type-generic - Fix strtod subnormal rounding (bug 30220) - More thoroughly test underflow / errno in tst-strtod-round - Test errno setting on strtod overflow in tst-strtod-round - Add tests of fread - stdio-common: Add new test for fdopen - libio: Attempt wide backup free only for non-legacy code - debug: Fix read error handling in pcprofiledump - elf: Fix tst-dlopen-tlsreinit1.out test dependency - elf: Avoid re-initializing already allocated TLS in dlopen (bug 31717) - elf: Clarify and invert second argument of _dl_allocate_tls_init - elf: Support recursive use of dynamic TLS in interposed malloc - 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 - string: strerror, strsignal cannot use buffer after dlmopen (bug 32026) - Define __libc_initial for the static libc - x86: Fix bug in strchrnul-evex512 [BZ #32078] - Adjust check-local-headers test for libaudit 4.0 - x32/cet: Support shadow stack during startup for Linux 6.10 - x86-64: Remove sysdeps/x86_64/x32/dl-machine.h - support: Add options list terminator to the test driver - manual/stdio: Further clarify putc, putwc, getc, and getwc - Fix name space violation in fortify wrappers (bug 32052) - resolv: Fix tst-resolv-short-response for older GCC (bug 32042) - Add mremap tests - mremap: Update manual entry - linux: Update the mremap C implementation [BZ #31968] - Enhanced test coverage for strncmp, wcsncmp - Enhance test coverage for strnlen, wcsnlen Resolves: RHEL-57776 Resolves: RHEL-57777 Resolves: RHEL-61392
141 lines
4.1 KiB
Diff
141 lines
4.1 KiB
Diff
commit 4e382ce01cce1ef2ab8548dc1dda2ad3046662d8
|
|
Author: Florian Weimer <fweimer@redhat.com>
|
|
Date: Tue Sep 10 12:40:27 2024 +0200
|
|
|
|
debug: Fix read error handling in pcprofiledump
|
|
|
|
The reading loops did not check for read failures. Addresses
|
|
a static analysis report.
|
|
|
|
Manually tested by compiling a program with the GCC's
|
|
-finstrument-functions option, running it with
|
|
“LD_PRELOAD=debug/libpcprofile.so PCPROFILE_OUTPUT=output-file”,
|
|
and reviewing the output of “debug/pcprofiledump output-file”.
|
|
|
|
(cherry picked from commit 89b088bf70c651c231bf27e644270d093b8f144a)
|
|
|
|
diff --git a/debug/pcprofiledump.c b/debug/pcprofiledump.c
|
|
index 049a9c2744df739a..94530f0cf92f0652 100644
|
|
--- a/debug/pcprofiledump.c
|
|
+++ b/debug/pcprofiledump.c
|
|
@@ -75,6 +75,44 @@ static struct argp argp =
|
|
options, parse_opt, args_doc, doc, NULL, more_help
|
|
};
|
|
|
|
+/* Try to read SIZE bytes from FD and store them on BUF. Terminate
|
|
+ the process upon read error. Also terminate the process if less
|
|
+ than SIZE bytes are remaining in the file. If !IN_HEADER, do not
|
|
+ terminate the process if the end of the file is encountered
|
|
+ immediately, before any bytes are read.
|
|
+
|
|
+ Returns true if SIZE bytes have been read, and false if no bytes
|
|
+ have been read due to an end-of-file condition. */
|
|
+static bool
|
|
+read_exactly (int fd, void *buffer, size_t size, bool in_header)
|
|
+{
|
|
+ char *p = buffer;
|
|
+ char *end = p + size;
|
|
+ while (p < end)
|
|
+ {
|
|
+ ssize_t ret = TEMP_FAILURE_RETRY (read (fd, p, end - p));
|
|
+ if (ret < 0)
|
|
+ {
|
|
+ if (in_header)
|
|
+ error (EXIT_FAILURE, errno, _("cannot read header"));
|
|
+ else
|
|
+ error (EXIT_FAILURE, errno, _("cannot read pointer pair"));
|
|
+ }
|
|
+ if (ret == 0)
|
|
+ {
|
|
+ if (p == buffer && !in_header)
|
|
+ /* Nothing has been read. */
|
|
+ return false;
|
|
+ if (in_header)
|
|
+ error (EXIT_FAILURE, 0, _("unexpected end of file in header"));
|
|
+ else
|
|
+ error (EXIT_FAILURE, 0,
|
|
+ _("unexpected end of file in pointer pair"));
|
|
+ }
|
|
+ p += ret;
|
|
+ }
|
|
+ return true;
|
|
+}
|
|
|
|
int
|
|
main (int argc, char *argv[])
|
|
@@ -110,8 +148,7 @@ main (int argc, char *argv[])
|
|
/* Read the first 4-byte word. It contains the information about
|
|
the word size and the endianness. */
|
|
uint32_t word;
|
|
- if (TEMP_FAILURE_RETRY (read (fd, &word, 4)) != 4)
|
|
- error (EXIT_FAILURE, errno, _("cannot read header"));
|
|
+ read_exactly (fd, &word, sizeof (word), true);
|
|
|
|
/* Check whether we have to swap the byte order. */
|
|
int must_swap = (word & 0x0fffffff) == bswap_32 (0xdeb00000);
|
|
@@ -121,56 +158,30 @@ main (int argc, char *argv[])
|
|
/* We have two loops, one for 32 bit pointers, one for 64 bit pointers. */
|
|
if (word == 0xdeb00004)
|
|
{
|
|
- union
|
|
- {
|
|
- uint32_t ptrs[2];
|
|
- char bytes[8];
|
|
- } pair;
|
|
+ uint32_t ptrs[2];
|
|
|
|
while (1)
|
|
{
|
|
- size_t len = sizeof (pair);
|
|
- size_t n;
|
|
-
|
|
- while (len > 0
|
|
- && (n = TEMP_FAILURE_RETRY (read (fd, &pair.bytes[8 - len],
|
|
- len))) != 0)
|
|
- len -= n;
|
|
-
|
|
- if (len != 0)
|
|
- /* Nothing to read. */
|
|
+ if (!read_exactly (fd, ptrs, sizeof (ptrs), false))
|
|
break;
|
|
|
|
printf ("this = %#010" PRIx32 ", caller = %#010" PRIx32 "\n",
|
|
- must_swap ? bswap_32 (pair.ptrs[0]) : pair.ptrs[0],
|
|
- must_swap ? bswap_32 (pair.ptrs[1]) : pair.ptrs[1]);
|
|
+ must_swap ? bswap_32 (ptrs[0]) : ptrs[0],
|
|
+ must_swap ? bswap_32 (ptrs[1]) : ptrs[1]);
|
|
}
|
|
}
|
|
else if (word == 0xdeb00008)
|
|
{
|
|
- union
|
|
- {
|
|
- uint64_t ptrs[2];
|
|
- char bytes[16];
|
|
- } pair;
|
|
+ uint64_t ptrs[2];
|
|
|
|
while (1)
|
|
{
|
|
- size_t len = sizeof (pair);
|
|
- size_t n;
|
|
-
|
|
- while (len > 0
|
|
- && (n = TEMP_FAILURE_RETRY (read (fd, &pair.bytes[8 - len],
|
|
- len))) != 0)
|
|
- len -= n;
|
|
-
|
|
- if (len != 0)
|
|
- /* Nothing to read. */
|
|
+ if (!read_exactly (fd, ptrs, sizeof (ptrs), false))
|
|
break;
|
|
|
|
printf ("this = %#018" PRIx64 ", caller = %#018" PRIx64 "\n",
|
|
- must_swap ? bswap_64 (pair.ptrs[0]) : pair.ptrs[0],
|
|
- must_swap ? bswap_64 (pair.ptrs[1]) : pair.ptrs[1]);
|
|
+ must_swap ? bswap_64 (ptrs[0]) : ptrs[0],
|
|
+ must_swap ? bswap_64 (ptrs[1]) : ptrs[1]);
|
|
}
|
|
}
|
|
else
|