284 lines
8.9 KiB
Diff
284 lines
8.9 KiB
Diff
From 1cb7d8b1afc7c71cfacfe017e0692c9064bf9818 Mon Sep 17 00:00:00 2001
|
|
From: Alan Modra <amodra@gmail.com>
|
|
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/readelf.c | 166 +++++++++++++++++++++++++++++------------------------
|
|
1 files changed, 90 insertions(+), 76 deletions(-)
|
|
|
|
diff --git a/binutils/readelf.c b/binutils/readelf.c
|
|
index c8ca66e..f76b9f6 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);
|
|
}
|
|
--
|
|
1.8.3.1
|
|
|