aboutsummaryrefslogtreecommitdiff
path: root/binutils
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2014-10-31 16:36:31 +0000
committerNick Clifton <nickc@redhat.com>2014-10-31 16:36:31 +0000
commitf54498b45795194df671207c6ef3d6cd6d0c0ebb (patch)
tree940ab0d69864094f00b010c1c678f3701bb6087f /binutils
parentfe06005387223e8a8b37e49036efe06b4062c7f4 (diff)
downloadgdb-f54498b45795194df671207c6ef3d6cd6d0c0ebb.zip
gdb-f54498b45795194df671207c6ef3d6cd6d0c0ebb.tar.gz
gdb-f54498b45795194df671207c6ef3d6cd6d0c0ebb.tar.bz2
Avoid allocating over-large buffers when parsing corrupt binaries.
PR binutils/17512 * coffgen.c (_bfd_coff_get_external_symbols): Do not try to load a symbol table bigger than the file. * elf.c (bfd_elf_get_str_section): Do not try to load a string table bigger than the file. * readelf.c (process_program_headers): Avoid memory exhaustion due to corrupt values in a dynamis segment header. (get_32bit_elf_symbols): Do not attempt to read an over-large section. (get_64bit_elf_symbols): Likewise.
Diffstat (limited to 'binutils')
-rw-r--r--binutils/ChangeLog9
-rw-r--r--binutils/readelf.c32
2 files changed, 37 insertions, 4 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index ec8a9e8..993f15c 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,5 +1,14 @@
2014-10-31 Nick Clifton <nickc@redhat.com>
+ PR binutils/17512
+ * readelf.c (process_program_headers): Avoid memory exhaustion due
+ to corrupt values in a dynamis segment header.
+ (get_32bit_elf_symbols): Do not attempt to read an over-large
+ section.
+ (get_64bit_elf_symbols): Likewise.
+
+2014-10-31 Nick Clifton <nickc@redhat.com>
+
* strings.c: Add new command line option --data to only scan the
initialized, loadable data secions of binaries. Choose the
default behaviour of --all or --data based upon a configure
diff --git a/binutils/readelf.c b/binutils/readelf.c
index aea0262..6ddc078 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -167,6 +167,7 @@
char * program_name = "readelf";
static long archive_file_offset;
static unsigned long archive_file_size;
+static bfd_size_type current_file_size;
static unsigned long dynamic_addr;
static bfd_size_type dynamic_size;
static unsigned int dynamic_nent;
@@ -4341,6 +4342,9 @@ process_program_headers (FILE * file)
}
}
+ if (do_segments)
+ putc ('\n', stdout);
+
switch (segment->p_type)
{
case PT_DYNAMIC:
@@ -4351,6 +4355,12 @@ process_program_headers (FILE * file)
section in the DYNAMIC segment. */
dynamic_addr = segment->p_offset;
dynamic_size = segment->p_filesz;
+ /* PR binutils/17512: Avoid corrupt dynamic section info in the segment. */
+ if (dynamic_addr + dynamic_size >= current_file_size)
+ {
+ error (_("the dynamic segment offset + size exceeds the size of the file\n"));
+ dynamic_addr = dynamic_size = 0;
+ }
/* Try to locate the .dynamic section. If there is
a section header table, we can easily locate it. */
@@ -4404,14 +4414,11 @@ process_program_headers (FILE * file)
error (_("Unable to read program interpreter name\n"));
if (do_segments)
- printf (_("\n [Requesting program interpreter: %s]"),
+ printf (_(" [Requesting program interpreter: %s]\n"),
program_interpreter);
}
break;
}
-
- if (do_segments)
- putc ('\n', stdout);
}
if (do_segments && section_headers != NULL && string_table != NULL)
@@ -4580,6 +4587,13 @@ get_32bit_elf_symbols (FILE * file,
goto exit_point;
}
+ if (section->sh_size > current_file_size)
+ {
+ error (_("Section %s has an invalid sh_size of 0x%lx\n"),
+ SECTION_NAME (section), section->sh_size);
+ goto exit_point;
+ }
+
number = section->sh_size / section->sh_entsize;
if (number * sizeof (Elf32_External_Sym) > section->sh_size + 1)
@@ -4660,6 +4674,13 @@ get_64bit_elf_symbols (FILE * file,
goto exit_point;
}
+ if (section->sh_size > current_file_size)
+ {
+ error (_("Section %s has an invalid sh_size of 0x%lx\n"),
+ SECTION_NAME (section), section->sh_size);
+ goto exit_point;
+ }
+
number = section->sh_size / section->sh_entsize;
if (number * sizeof (Elf64_External_Sym) > section->sh_size + 1)
@@ -14886,6 +14907,8 @@ process_file (char * file_name)
return 1;
}
+ current_file_size = (bfd_size_type) statbuf.st_size;
+
if (memcmp (armag, ARMAG, SARMAG) == 0)
ret = process_archive (file_name, file, FALSE);
else if (memcmp (armag, ARMAGT, SARMAG) == 0)
@@ -14903,6 +14926,7 @@ process_file (char * file_name)
fclose (file);
+ current_file_size = 0;
return ret;
}