From 1cb7d8b1afc7c71cfacfe017e0692c9064bf9818 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Thu, 19 Mar 2020 10:10:32 +1030 Subject: [PATCH] readelf leak in process_archive * readelf.c (process_archive): Always return via path freeing memory. Formatting. --- binutils/ChangeLog | 5 ++ binutils/readelf.c | 166 ++++++++++++++++++++++++--------------------- 2 files changed, 95 insertions(+), 76 deletions(-) diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 7522653315..e52a14f836 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,8 @@ +2020-03-19 Alan Modra + + * readelf.c (process_archive): Always return via path freeing + memory. Formatting. + 2020-03-19 Alan Modra * readelf.c (process_netbsd_elf_note): Validate descsz before diff --git a/binutils/readelf.c b/binutils/readelf.c index c8ca66e52c..f76b9f6d8e 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -20256,49 +20256,58 @@ process_archive (Filedata * filedata, bfd_boolean is_thin_archive) if (do_archive_index) { if (arch.sym_table == NULL) - error (_("%s: unable to dump the index as none was found\n"), filedata->file_name); + error (_("%s: unable to dump the index as none was found\n"), + filedata->file_name); else { unsigned long i, l; unsigned long current_pos; - printf (_("Index of archive %s: (%lu entries, 0x%lx bytes in the symbol table)\n"), - filedata->file_name, (unsigned long) arch.index_num, arch.sym_size); + printf (_("Index of archive %s: (%lu entries, 0x%lx bytes " + "in the symbol table)\n"), + filedata->file_name, (unsigned long) arch.index_num, + arch.sym_size); current_pos = ftell (filedata->handle); for (i = l = 0; i < arch.index_num; i++) { - if ((i == 0) || ((i > 0) && (arch.index_array[i] != arch.index_array[i - 1]))) - { - char * member_name; - - member_name = get_archive_member_name_at (&arch, arch.index_array[i], &nested_arch); + if (i == 0 + || (i > 0 && arch.index_array[i] != arch.index_array[i - 1])) + { + char * member_name + = get_archive_member_name_at (&arch, arch.index_array[i], + &nested_arch); - if (member_name != NULL) - { - char * qualified_name = make_qualified_name (&arch, &nested_arch, member_name); + if (member_name != NULL) + { + char * qualified_name + = make_qualified_name (&arch, &nested_arch, + member_name); - if (qualified_name != NULL) - { - printf (_("Contents of binary %s at offset "), qualified_name); + if (qualified_name != NULL) + { + printf (_("Contents of binary %s at offset "), + qualified_name); (void) print_vma (arch.index_array[i], PREFIX_HEX); putchar ('\n'); - free (qualified_name); - } + free (qualified_name); + } free (member_name); } } if (l >= arch.sym_size) { - error (_("%s: end of the symbol table reached before the end of the index\n"), + error (_("%s: end of the symbol table reached " + "before the end of the index\n"), filedata->file_name); ret = FALSE; break; } /* PR 17531: file: 0b6630b2. */ - printf ("\t%.*s\n", (int) (arch.sym_size - l), arch.sym_table + l); + printf ("\t%.*s\n", + (int) (arch.sym_size - l), arch.sym_table + l); l += strnlen (arch.sym_table + l, arch.sym_size - l) + 1; } @@ -20322,7 +20331,8 @@ process_archive (Filedata * filedata, bfd_boolean is_thin_archive) if (fseek (filedata->handle, current_pos, SEEK_SET) != 0) { - error (_("%s: failed to seek back to start of object files in the archive\n"), + error (_("%s: failed to seek back to start of object files " + "in the archive\n"), filedata->file_name); ret = FALSE; goto out; @@ -20347,34 +20357,37 @@ process_archive (Filedata * filedata, bfd_boolean is_thin_archive) /* Read the next archive header. */ if (fseek (filedata->handle, arch.next_arhdr_offset, SEEK_SET) != 0) - { - error (_("%s: failed to seek to next archive header\n"), arch.file_name); - return FALSE; - } + { + error (_("%s: failed to seek to next archive header\n"), + arch.file_name); + ret = FALSE; + break; + } got = fread (&arch.arhdr, 1, sizeof arch.arhdr, filedata->handle); if (got != sizeof arch.arhdr) - { - if (got == 0) + { + if (got == 0) break; /* PR 24049 - we cannot use filedata->file_name as this will have already been freed. */ error (_("%s: failed to read archive header\n"), arch.file_name); - ret = FALSE; - break; - } + ret = FALSE; + break; + } if (memcmp (arch.arhdr.ar_fmag, ARFMAG, 2) != 0) - { - error (_("%s: did not find a valid archive header\n"), arch.file_name); - ret = FALSE; - break; - } + { + error (_("%s: did not find a valid archive header\n"), + arch.file_name); + ret = FALSE; + break; + } arch.next_arhdr_offset += sizeof arch.arhdr; archive_file_size = strtoul (arch.arhdr.ar_size, NULL, 10); if (archive_file_size & 01) - ++archive_file_size; + ++archive_file_size; name = get_archive_member_name (&arch, &nested_arch); if (name == NULL) @@ -20395,45 +20408,45 @@ process_archive (Filedata * filedata, bfd_boolean is_thin_archive) } if (is_thin_archive && arch.nested_member_origin == 0) - { - /* This is a proxy for an external member of a thin archive. */ - Filedata * member_filedata; - char * member_file_name = adjust_relative_path + { + /* This is a proxy for an external member of a thin archive. */ + Filedata * member_filedata; + char * member_file_name = adjust_relative_path (filedata->file_name, name, namelen); free (name); - if (member_file_name == NULL) - { + if (member_file_name == NULL) + { free (qualified_name); - ret = FALSE; - break; - } + ret = FALSE; + break; + } - member_filedata = open_file (member_file_name); - if (member_filedata == NULL) - { - error (_("Input file '%s' is not readable.\n"), member_file_name); - free (member_file_name); + member_filedata = open_file (member_file_name); + if (member_filedata == NULL) + { + error (_("Input file '%s' is not readable.\n"), member_file_name); + free (member_file_name); free (qualified_name); - ret = FALSE; - break; - } + ret = FALSE; + break; + } - archive_file_offset = arch.nested_member_origin; + archive_file_offset = arch.nested_member_origin; member_filedata->file_name = qualified_name; - if (! process_object (member_filedata)) + if (! process_object (member_filedata)) ret = FALSE; - close_file (member_filedata); - free (member_file_name); + close_file (member_filedata); + free (member_file_name); free (qualified_name); - } + } else if (is_thin_archive) - { - Filedata thin_filedata; + { + Filedata thin_filedata; - memset (&thin_filedata, 0, sizeof (thin_filedata)); + memset (&thin_filedata, 0, sizeof (thin_filedata)); /* PR 15140: Allow for corrupt thin archives. */ if (nested_arch.file == NULL) @@ -20447,35 +20460,36 @@ process_archive (Filedata * filedata, bfd_boolean is_thin_archive) } free (name); - /* This is a proxy for a member of a nested archive. */ - archive_file_offset = arch.nested_member_origin + sizeof arch.arhdr; + /* This is a proxy for a member of a nested archive. */ + archive_file_offset = arch.nested_member_origin + sizeof arch.arhdr; - /* The nested archive file will have been opened and setup by - get_archive_member_name. */ - if (fseek (nested_arch.file, archive_file_offset, SEEK_SET) != 0) - { - error (_("%s: failed to seek to archive member.\n"), nested_arch.file_name); + /* The nested archive file will have been opened and setup by + get_archive_member_name. */ + if (fseek (nested_arch.file, archive_file_offset, SEEK_SET) != 0) + { + error (_("%s: failed to seek to archive member.\n"), + nested_arch.file_name); free (qualified_name); - ret = FALSE; - break; - } + ret = FALSE; + break; + } thin_filedata.handle = nested_arch.file; thin_filedata.file_name = qualified_name; - if (! process_object (& thin_filedata)) + if (! process_object (& thin_filedata)) ret = FALSE; - } + } else - { + { free (name); - archive_file_offset = arch.next_arhdr_offset; - arch.next_arhdr_offset += archive_file_size; + archive_file_offset = arch.next_arhdr_offset; + arch.next_arhdr_offset += archive_file_size; filedata->file_name = qualified_name; - if (! process_object (filedata)) + if (! process_object (filedata)) ret = FALSE; - } + } free (qualified_name); } -- 2.34.1