summaryrefslogtreecommitdiff
path: root/binutils/readelf.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@bigpond.net.au>2013-02-27 12:40:15 +0000
committerAlan Modra <amodra@bigpond.net.au>2013-02-27 12:40:15 +0000
commitdb3aa69624c06f72317dc27c4658d43f56b5513b (patch)
tree0f9cca1b429213ca2a198569b4cd71d8a5a0a945 /binutils/readelf.c
parent517794c88d7807d88b0afb9deab4133c3483e5fd (diff)
downloadbinutils-redhat-db3aa69624c06f72317dc27c4658d43f56b5513b.tar.gz
PR binutils/15191
* readelf.c (offsetof): Define. (CHECK_ENTSIZE_VALUES): Remove extraneous indefinite article. (process_corefile_note_segment): Allow notes without name or desc. Combine out-of-range checks. Disallow "negative" notesz or descsz.
Diffstat (limited to 'binutils/readelf.c')
-rw-r--r--binutils/readelf.c87
1 files changed, 40 insertions, 47 deletions
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 7b9d102af7..28172f22a3 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -160,6 +160,10 @@
#include "safe-ctype.h"
#include "filenames.h"
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &(((TYPE *) 0)->MEMBER))
+#endif
+
char * program_name = "readelf";
static long archive_file_offset;
static unsigned long archive_file_size;
@@ -4754,7 +4758,7 @@ process_section_headers (FILE * file)
bfd_size_type expected_entsize = is_32bit_elf ? size32 : size64; \
if (section->sh_entsize != expected_entsize) \
{ \
- error (_("Section %d has invalid an sh_entsize of %" BFD_VMA_FMT "x\n"), \
+ error (_("Section %d has invalid sh_entsize of %" BFD_VMA_FMT "x\n"), \
i, section->sh_entsize); \
error (_("(Using the expected size of %d for the rest of this dump)\n"), \
(int) expected_entsize); \
@@ -13340,13 +13344,12 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
Elf_External_Note * pnotes;
Elf_External_Note * external;
int res = 1;
- bfd_signed_vma data_remaining;
if (length <= 0)
return 0;
pnotes = (Elf_External_Note *) get_data (NULL, file, offset, 1, length,
- _("notes"));
+ _("notes"));
if (pnotes == NULL)
return 0;
@@ -13356,79 +13359,69 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
(unsigned long) offset, (unsigned long) length);
printf (_(" %-20s %10s\tDescription\n"), _("Owner"), _("Data size"));
- data_remaining = length;
- while (external < (Elf_External_Note *) ((char *) pnotes + length))
+ while ((char *) external < (char *) pnotes + length)
{
- Elf_External_Note * next;
Elf_Internal_Note inote;
+ size_t min_notesz;
+ char *next;
char * temp = NULL;
+ size_t data_remaining = ((char *) pnotes + length) - (char *) external;
if (!is_ia64_vms ())
- {
+ {
/* PR binutils/15191
Make sure that there is enough data to read. */
- if (data_remaining < sizeof * next)
+ min_notesz = offsetof (Elf_External_Note, name);
+ if (data_remaining < min_notesz)
{
warn (_("Corrupt note: only %d bytes remain, not enough for a full note\n"),
(int) data_remaining);
break;
}
- inote.type = BYTE_GET (external->type);
- inote.namesz = BYTE_GET (external->namesz);
- inote.namedata = external->name;
- inote.descsz = BYTE_GET (external->descsz);
- inote.descdata = inote.namedata + align_power (inote.namesz, 2);
- inote.descpos = offset + (inote.descdata - (char *) pnotes);
-
- next = (Elf_External_Note *) (inote.descdata + align_power (inote.descsz, 2));
- }
+ inote.type = BYTE_GET (external->type);
+ inote.namesz = BYTE_GET (external->namesz);
+ inote.namedata = external->name;
+ inote.descsz = BYTE_GET (external->descsz);
+ inote.descdata = inote.namedata + align_power (inote.namesz, 2);
+ inote.descpos = offset + (inote.descdata - (char *) pnotes);
+ next = inote.descdata + align_power (inote.descsz, 2);
+ }
else
- {
- Elf64_External_VMS_Note *vms_external;
+ {
+ Elf64_External_VMS_Note *vms_external;
/* PR binutils/15191
Make sure that there is enough data to read. */
- if (data_remaining < sizeof * vms_external)
+ min_notesz = offsetof (Elf64_External_VMS_Note, name);
+ if (data_remaining < min_notesz)
{
warn (_("Corrupt note: only %d bytes remain, not enough for a full note\n"),
(int) data_remaining);
break;
}
-
- vms_external = (Elf64_External_VMS_Note *) external;
- inote.type = BYTE_GET (vms_external->type);
- inote.namesz = BYTE_GET (vms_external->namesz);
- inote.namedata = vms_external->name;
- inote.descsz = BYTE_GET (vms_external->descsz);
- inote.descdata = inote.namedata + align_power (inote.namesz, 3);
- inote.descpos = offset + (inote.descdata - (char *) pnotes);
-
- next = (Elf_External_Note *)
- (inote.descdata + align_power (inote.descsz, 3));
- }
- data_remaining -= ((char *) next - (char *) external);
- if (data_remaining < 0)
+ vms_external = (Elf64_External_VMS_Note *) external;
+ inote.type = BYTE_GET (vms_external->type);
+ inote.namesz = BYTE_GET (vms_external->namesz);
+ inote.namedata = vms_external->name;
+ inote.descsz = BYTE_GET (vms_external->descsz);
+ inote.descdata = inote.namedata + align_power (inote.namesz, 3);
+ inote.descpos = offset + (inote.descdata - (char *) pnotes);
+ next = inote.descdata + align_power (inote.descsz, 3);
+ }
+
+ if (inote.descdata < (char *) external + min_notesz
+ || next < (char *) external + min_notesz
+ || data_remaining < (size_t)(next - (char *) external))
{
- warn (_("note with invalid namesz &/or descsz found at offset 0x%lx\n"),
+ warn (_("note with invalid namesz and/or descsz found at offset 0x%lx\n"),
(unsigned long) ((char *) external - (char *) pnotes));
warn (_(" type: 0x%lx, namesize: 0x%08lx, descsize: 0x%08lx\n"),
inote.type, inote.namesz, inote.descsz);
break;
}
- external = next;
-
- /* Prevent out-of-bounds indexing. */
- if (inote.namedata + inote.namesz > (char *) pnotes + length
- || inote.namedata + inote.namesz < inote.namedata)
- {
- warn (_("note with invalid namesz found at offset 0x%lx\n"),
- (unsigned long) ((char *) external - (char *) pnotes));
- warn (_(" type: 0x%lx, namesize: 0x%08lx, descsize: 0x%08lx\n"),
- inote.type, inote.namesz, inote.descsz);
- break;
- }
+ external = (Elf_External_Note *) next;
/* Verify that name is null terminated. It appears that at least
one version of Linux (RedHat 6.0) generates corefiles that don't