From: Alan Modra Date: Sat, 14 Mar 2020 01:20:22 +0000 (+1030) Subject: readelf large memory allocation X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=780f96aed2b4db1014e8fa2b50118676d8af0e46;p=binutils-gdb.git readelf large memory allocation * elfcomm.h (setup_archive): Update prototype. * elfcomm.c (setup_archive): Add file_size parameter and sanity check longnames_size. (setup_nested_archive): Get file size and pass to setup_archive. * elfedit.c (process_archive): Likewise. * readelf.c (process_archive): Pass filedata->file_size to setup_archive. --- diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 9a64b0de245..5101b8c9912 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,13 @@ +2020-03-14 Alan Modra + + * elfcomm.h (setup_archive): Update prototype. + * elfcomm.c (setup_archive): Add file_size parameter and sanity + check longnames_size. + (setup_nested_archive): Get file size and pass to setup_archive. + * elfedit.c (process_archive): Likewise. + * readelf.c (process_archive): Pass filedata->file_size to + setup_archive. + 2020-03-14 Alan Modra * readelf.c (dump_section_as_strings): Free memory on error exit. diff --git a/binutils/elfcomm.c b/binutils/elfcomm.c index 3060ff178e1..e5c6a32c6da 100644 --- a/binutils/elfcomm.c +++ b/binutils/elfcomm.c @@ -607,8 +607,8 @@ process_archive_index_and_symbols (struct archive_info * arch, int setup_archive (struct archive_info *arch, const char *file_name, - FILE *file, bfd_boolean is_thin_archive, - bfd_boolean read_symbols) + FILE *file, bfd_size_type file_size, + bfd_boolean is_thin_archive, bfd_boolean read_symbols) { size_t got; @@ -671,7 +671,8 @@ setup_archive (struct archive_info *arch, const char *file_name, return 1; } /* PR 17531: file: 639d6a26. */ - if ((signed long) arch->longnames_size < 0) + if (arch->longnames_size > file_size + || (signed long) arch->longnames_size < 0) { error (_("%s: long name table is too big, (size = 0x%lx)\n"), file_name, arch->longnames_size); @@ -713,6 +714,7 @@ setup_nested_archive (struct archive_info *nested_arch, const char *member_file_name) { FILE * member_file; + struct stat statbuf; /* Have we already setup this archive? */ if (nested_arch->file_name != NULL @@ -727,8 +729,10 @@ setup_nested_archive (struct archive_info *nested_arch, member_file = fopen (member_file_name, "rb"); if (member_file == NULL) return 1; + if (fstat (fileno (member_file), &statbuf) < 0) + return 1; return setup_archive (nested_arch, member_file_name, member_file, - FALSE, FALSE); + statbuf.st_size, FALSE, FALSE); } /* Release the memory used for the archive information. */ diff --git a/binutils/elfcomm.h b/binutils/elfcomm.h index 9bf3c41edbd..731d3dbd346 100644 --- a/binutils/elfcomm.h +++ b/binutils/elfcomm.h @@ -74,7 +74,7 @@ extern char *adjust_relative_path (const char *, const char *, unsigned long); /* Read the symbol table and long-name table from an archive. */ extern int setup_archive (struct archive_info *, const char *, FILE *, - bfd_boolean, bfd_boolean); + bfd_size_type, bfd_boolean, bfd_boolean); /* Open and setup a nested archive, if not already open. */ extern int setup_nested_archive (struct archive_info *, const char *); diff --git a/binutils/elfedit.c b/binutils/elfedit.c index 3a14c60ece6..d0e4e95f4d6 100644 --- a/binutils/elfedit.c +++ b/binutils/elfedit.c @@ -541,6 +541,7 @@ process_archive (const char * file_name, FILE * file, struct archive_info nested_arch; size_t got; int ret; + struct stat statbuf; /* The ARCH structure is used to hold information about this archive. */ arch.file_name = NULL; @@ -558,7 +559,9 @@ process_archive (const char * file_name, FILE * file, nested_arch.sym_table = NULL; nested_arch.longnames = NULL; - if (setup_archive (&arch, file_name, file, is_thin_archive, FALSE) != 0) + if (fstat (fileno (file), &statbuf) < 0 + || setup_archive (&arch, file_name, file, statbuf.st_size, + is_thin_archive, FALSE) != 0) { ret = 1; goto out; diff --git a/binutils/readelf.c b/binutils/readelf.c index b106e8c816f..0f8a0809c55 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -20247,7 +20247,8 @@ process_archive (Filedata * filedata, bfd_boolean is_thin_archive) nested_arch.longnames = NULL; if (setup_archive (&arch, filedata->file_name, filedata->handle, - is_thin_archive, do_archive_index) != 0) + filedata->file_size, is_thin_archive, + do_archive_index) != 0) { ret = FALSE; goto out;