From 15b42fb01d638bf1ae9c7086727cd0a608237843 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 27 Feb 2013 12:40:15 +0000 Subject: [PATCH] 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. --- binutils/ChangeLog | 25 ++++++++----- binutils/readelf.c | 87 +++++++++++++++++++++------------------------- 2 files changed, 57 insertions(+), 55 deletions(-) diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 8d06ecb45a5..01ac46d04fb 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,12 @@ +2013-02-27 Alan Modra + + 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. + 2013-02-26 Nick Clifton PR binutils/15191 @@ -78,14 +87,14 @@ 2013-01-25 Cary Coutant - * dwarf.c (display_loc_list): Update offset for each line - printed. - (print_addr_index): New function. - (display_loc_list_dwo): Update offset for each line printed. - Fix problems displaying loclists in .dwo files. Add support - for type 4 entries. - (display_debug_loc): Remove custom header for .dwo files. - (display_debug_addr): Adjust formatting. + * dwarf.c (display_loc_list): Update offset for each line + printed. + (print_addr_index): New function. + (display_loc_list_dwo): Update offset for each line printed. + Fix problems displaying loclists in .dwo files. Add support + for type 4 entries. + (display_debug_loc): Remove custom header for .dwo files. + (display_debug_addr): Adjust formatting. 2013-01-25 Marco Atzeri diff --git a/binutils/readelf.c b/binutils/readelf.c index 7b9d102af73..28172f22a3a 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 -- 2.39.2