mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-26 19:23:34 +08:00
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”.
This commit is contained in:
parent
e82a7cb162
commit
89b088bf70
@ -75,6 +75,44 @@ static struct argp argp =
|
|||||||
options, parse_opt, args_doc, doc, NULL, more_help
|
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
|
int
|
||||||
main (int argc, char *argv[])
|
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
|
/* Read the first 4-byte word. It contains the information about
|
||||||
the word size and the endianness. */
|
the word size and the endianness. */
|
||||||
uint32_t word;
|
uint32_t word;
|
||||||
if (TEMP_FAILURE_RETRY (read (fd, &word, 4)) != 4)
|
read_exactly (fd, &word, sizeof (word), true);
|
||||||
error (EXIT_FAILURE, errno, _("cannot read header"));
|
|
||||||
|
|
||||||
/* Check whether we have to swap the byte order. */
|
/* Check whether we have to swap the byte order. */
|
||||||
int must_swap = (word & 0x0fffffff) == bswap_32 (0xdeb00000);
|
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. */
|
/* We have two loops, one for 32 bit pointers, one for 64 bit pointers. */
|
||||||
if (word == 0xdeb00004)
|
if (word == 0xdeb00004)
|
||||||
{
|
{
|
||||||
union
|
uint32_t ptrs[2];
|
||||||
{
|
|
||||||
uint32_t ptrs[2];
|
|
||||||
char bytes[8];
|
|
||||||
} pair;
|
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
size_t len = sizeof (pair);
|
if (!read_exactly (fd, ptrs, sizeof (ptrs), false))
|
||||||
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. */
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
printf ("this = %#010" PRIx32 ", caller = %#010" PRIx32 "\n",
|
printf ("this = %#010" PRIx32 ", caller = %#010" PRIx32 "\n",
|
||||||
must_swap ? bswap_32 (pair.ptrs[0]) : pair.ptrs[0],
|
must_swap ? bswap_32 (ptrs[0]) : ptrs[0],
|
||||||
must_swap ? bswap_32 (pair.ptrs[1]) : pair.ptrs[1]);
|
must_swap ? bswap_32 (ptrs[1]) : ptrs[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (word == 0xdeb00008)
|
else if (word == 0xdeb00008)
|
||||||
{
|
{
|
||||||
union
|
uint64_t ptrs[2];
|
||||||
{
|
|
||||||
uint64_t ptrs[2];
|
|
||||||
char bytes[16];
|
|
||||||
} pair;
|
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
size_t len = sizeof (pair);
|
if (!read_exactly (fd, ptrs, sizeof (ptrs), false))
|
||||||
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. */
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
printf ("this = %#018" PRIx64 ", caller = %#018" PRIx64 "\n",
|
printf ("this = %#018" PRIx64 ", caller = %#018" PRIx64 "\n",
|
||||||
must_swap ? bswap_64 (pair.ptrs[0]) : pair.ptrs[0],
|
must_swap ? bswap_64 (ptrs[0]) : ptrs[0],
|
||||||
must_swap ? bswap_64 (pair.ptrs[1]) : pair.ptrs[1]);
|
must_swap ? bswap_64 (ptrs[1]) : ptrs[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
Loading…
Reference in New Issue
Block a user