diff options
author | Alan Modra <amodra@gmail.com> | 2013-02-27 12:40:15 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2013-02-27 12:40:15 +0000 |
commit | 15b42fb01d638bf1ae9c7086727cd0a608237843 (patch) | |
tree | c289518e0d2c3ec3c20d69641f4e575d64cb1ff9 /binutils/readelf.c | |
parent | 727f7031022464188dc580e84b3d232c21b39d10 (diff) | |
download | gdb-15b42fb01d638bf1ae9c7086727cd0a608237843.zip gdb-15b42fb01d638bf1ae9c7086727cd0a608237843.tar.gz gdb-15b42fb01d638bf1ae9c7086727cd0a608237843.tar.bz2 |
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.c | 87 |
1 files changed, 40 insertions, 47 deletions
diff --git a/binutils/readelf.c b/binutils/readelf.c index 7b9d102..28172f2 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 |