From 0680331375436d4dd60428de66591153a84550bd Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Tue, 5 Jul 2005 11:43:55 +0000 Subject: [PATCH] Add check to avoid corrupt input files whose section sizes are greater than the size of the input file. --- binutils/ChangeLog | 9 ++++++ binutils/strings.c | 83 +++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 75 insertions(+), 17 deletions(-) diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 2498494..b25d429 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,12 @@ +2005-07-05 Dmitry V. Levin + Nick Clifton + + * strings.c (filename_and_size_t): New typedef. + (strings_a_section): Skip sections with size greater or equal to + the file size. Cache the file size to avoid repeated stat()s. + (strings_object_file): Pass filename_and_size_t argument to + strings_a_section() via bfd_map_over_sections(). + 2005-07-04 Alan Modra PR 1004 diff --git a/binutils/strings.c b/binutils/strings.c index fda63bd..bdfca226 100644 --- a/binutils/strings.c +++ b/binutils/strings.c @@ -1,6 +1,6 @@ /* strings -- print the strings of printable characters in files Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004 Free Software Foundation, Inc. + 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -151,6 +151,15 @@ static struct option long_options[] = {NULL, 0, NULL, 0} }; +/* Records the size of a named file so that we + do not repeatedly run bfd_stat() on it. */ + +typedef struct +{ + const char * filename; + bfd_size_type filesize; +} filename_and_size_t; + static void strings_a_section (bfd *, asection *, void *); static bfd_boolean strings_object_file (const char *); static bfd_boolean strings_file (char *file); @@ -314,27 +323,62 @@ main (int argc, char **argv) return (exit_status); } -/* Scan section SECT of the file ABFD, whose printable name is FILE. - If it contains initialized data, - set `got_a_section' and print the strings in it. */ +/* Scan section SECT of the file ABFD, whose printable name is in + ARG->filename and whose size might be in ARG->filesize. If it + contains initialized data set `got_a_section' and print the + strings in it. + + FIXME: We ought to be able to return error codes/messages for + certain conditions. */ static void -strings_a_section (bfd *abfd, asection *sect, void *filearg) +strings_a_section (bfd *abfd, asection *sect, void *arg) { - const char *file = (const char *) filearg; + filename_and_size_t * filename_and_sizep; + bfd_size_type *filesizep; + bfd_size_type sectsize; + void *mem; + + if ((sect->flags & DATA_FLAGS) != DATA_FLAGS) + return; + + sectsize = bfd_get_section_size (sect); + + if (sectsize <= 0) + return; + + /* Get the size of the file. This might have been cached for us. */ + filename_and_sizep = (filename_and_size_t *) arg; + filesizep = & filename_and_sizep->filesize; + + if (*filesizep == 0) + { + struct stat st; + + if (bfd_stat (abfd, &st)) + return; + + /* Cache the result so that we do not repeatedly stat this file. */ + *filesizep = st.st_size; + } - if ((sect->flags & DATA_FLAGS) == DATA_FLAGS) + /* Compare the size of the section against the size of the file. + If the section is bigger then the file must be corrupt and + we should not try dumping it. */ + if (sectsize >= *filesizep) + return; + + mem = xmalloc (sectsize); + + if (bfd_get_section_contents (abfd, sect, mem, (file_ptr) 0, sectsize)) { - bfd_size_type sz = bfd_get_section_size (sect); - void *mem = xmalloc (sz); + got_a_section = TRUE; - if (bfd_get_section_contents (abfd, sect, mem, (file_ptr) 0, sz)) - { - got_a_section = TRUE; - print_strings (file, (FILE *) NULL, sect->filepos, 0, sz, mem); - } - free (mem); + print_strings (filename_and_sizep->filename, NULL, sect->filepos, + 0, sectsize, mem); } + + free (mem); } /* Scan all of the sections in FILE, and print the strings @@ -346,7 +390,10 @@ strings_a_section (bfd *abfd, asection *sect, void *filearg) static bfd_boolean strings_object_file (const char *file) { - bfd *abfd = bfd_openr (file, target); + filename_and_size_t filename_and_size; + bfd *abfd; + + abfd = bfd_openr (file, target); if (abfd == NULL) /* Treat the file as a non-object file. */ @@ -362,7 +409,9 @@ strings_object_file (const char *file) } got_a_section = FALSE; - bfd_map_over_sections (abfd, strings_a_section, (void *) file); + filename_and_size.filename = file; + filename_and_size.filesize = 0; + bfd_map_over_sections (abfd, strings_a_section, & filename_and_size); if (!bfd_close (abfd)) { -- 2.7.4