readelf leak in process_archive

* readelf.c (process_archive): Always return via path freeing
	memory.  Formatting.
This commit is contained in:
Alan Modra 2020-03-19 10:10:32 +10:30
parent b966f55ffa
commit 1cb7d8b1af
2 changed files with 95 additions and 76 deletions

View File

@ -1,3 +1,8 @@
2020-03-19 Alan Modra <amodra@gmail.com>
* readelf.c (process_archive): Always return via path freeing
memory. Formatting.
2020-03-19 Alan Modra <amodra@gmail.com>
* readelf.c (process_netbsd_elf_note): Validate descsz before

View File

@ -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;
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);
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);
}