mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-15 04:31:49 +08:00
PR25993, read of freed memory
ldmain.c:add_archive_element copies file name pointers from the bfd to a lang_input_statement_type. input->filename = abfd->filename; input->local_sym_name = abfd->filename; This results in stale pointers when twiddling the bfd filename in places like the pe ld after_open. So don't free the bfd filename, and make copies using bfd_alloc memory that won't result in small memory leaks that annoy memory checkers. PR 25993 bfd/ * archive.c (_bfd_get_elt_at_filepos): Don't strdup filename, use bfd_set_filename. * elfcode.h (_bfd_elf_bfd_from_remote_memory): Likewise. * mach-o.c (bfd_mach_o_fat_member_init): Likewise. * opncls.c (bfd_fopen, bfd_openstreamr, bfd_openr_iovec, bfd_openw), (bfd_create): Likewise. (_bfd_delete_bfd): Don't free filename. (bfd_set_filename): Copy filename param to bfd_alloc'd memory, return pointer to the copy or NULL on alloc fail. * vms-lib.c (_bfd_vms_lib_get_module): Free newname and test result of bfd_set_filename. * bfd-in2.h: Regenerate. gdb/ * solib-darwin.c (darwin_bfd_open): Don't strdup pathname for bfd_set_filename. * solib-aix.c (solib_aix_bfd_open): Use std::string for name passed to bfd_set_filename. * symfile-mem.c (add_vsyscall_page): Likewise for string passed to symbol_file_add_from_memory. (symbol_file_add_from_memory): Make name param a const char* and don't strdup. ld/ * emultempl/pe.em (gld_${EMULATION_NAME}_after_open): Don't copy other_bfd_filename for bfd_set_filename, and test result of bfd_set_filename call. Don't create a new is->filename, simply copy from bfd filename. Free new_name after bfd_set_filename. * emultempl/pep.em (gld_${EMULATION_NAME}_after_open): Likewise.
This commit is contained in:
parent
84f800117f
commit
7b958a48e1
@ -1,3 +1,19 @@
|
||||
2020-05-20 Alan Modra <amodra@gmail.com>
|
||||
|
||||
PR 25993
|
||||
* archive.c (_bfd_get_elt_at_filepos): Don't strdup filename,
|
||||
use bfd_set_filename.
|
||||
* elfcode.h (_bfd_elf_bfd_from_remote_memory): Likewise.
|
||||
* mach-o.c (bfd_mach_o_fat_member_init): Likewise.
|
||||
* opncls.c (bfd_fopen, bfd_openstreamr, bfd_openr_iovec, bfd_openw),
|
||||
(bfd_create): Likewise.
|
||||
(_bfd_delete_bfd): Don't free filename.
|
||||
(bfd_set_filename): Copy filename param to bfd_alloc'd memory,
|
||||
return pointer to the copy or NULL on alloc fail.
|
||||
* vms-lib.c (_bfd_vms_lib_get_module): Free newname and test
|
||||
result of bfd_set_filename.
|
||||
* bfd-in2.h: Regenerate.
|
||||
|
||||
2020-05-20 Alan Modra <amodra@gmail.com>
|
||||
|
||||
PR 26011
|
||||
|
@ -737,8 +737,7 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
|
||||
else
|
||||
{
|
||||
n_bfd->origin = n_bfd->proxy_origin;
|
||||
n_bfd->filename = bfd_strdup (filename);
|
||||
if (n_bfd->filename == NULL)
|
||||
if (!bfd_set_filename (n_bfd, filename))
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -643,7 +643,7 @@ bfd_boolean bfd_fill_in_gnu_debuglink_section
|
||||
|
||||
char *bfd_follow_build_id_debuglink (bfd *abfd, const char *dir);
|
||||
|
||||
void bfd_set_filename (bfd *abfd, char *filename);
|
||||
const char *bfd_set_filename (bfd *abfd, const char *filename);
|
||||
|
||||
/* Extracted from libbfd.c. */
|
||||
|
||||
|
@ -1680,7 +1680,6 @@ NAME(_bfd_elf,bfd_from_remote_memory)
|
||||
bfd_vma high_offset;
|
||||
bfd_vma shdr_end;
|
||||
bfd_vma loadbase; /* Bytes. */
|
||||
char *filename;
|
||||
size_t amt;
|
||||
unsigned int opb = bfd_octets_per_byte (templ, NULL);
|
||||
|
||||
@ -1894,22 +1893,14 @@ NAME(_bfd_elf,bfd_from_remote_memory)
|
||||
free (contents);
|
||||
return NULL;
|
||||
}
|
||||
filename = bfd_strdup ("<in-memory>");
|
||||
if (filename == NULL)
|
||||
{
|
||||
free (bim);
|
||||
free (contents);
|
||||
return NULL;
|
||||
}
|
||||
nbfd = _bfd_new_bfd ();
|
||||
if (nbfd == NULL)
|
||||
if (nbfd == NULL
|
||||
|| !bfd_set_filename (nbfd, "<in-memory>"))
|
||||
{
|
||||
free (filename);
|
||||
free (bim);
|
||||
free (contents);
|
||||
return NULL;
|
||||
}
|
||||
nbfd->filename = filename;
|
||||
nbfd->xvec = templ->xvec;
|
||||
bim->size = high_offset;
|
||||
bim->buffer = contents;
|
||||
|
17
bfd/mach-o.c
17
bfd/mach-o.c
@ -5573,26 +5573,23 @@ bfd_mach_o_fat_member_init (bfd *abfd,
|
||||
struct areltdata *areltdata;
|
||||
/* Create the member filename. Use ARCH_NAME. */
|
||||
const bfd_arch_info_type *ap = bfd_lookup_arch (arch_type, arch_subtype);
|
||||
char *filename;
|
||||
const char *filename;
|
||||
|
||||
if (ap)
|
||||
{
|
||||
/* Use the architecture name if known. */
|
||||
filename = bfd_strdup (ap->printable_name);
|
||||
if (filename == NULL)
|
||||
return FALSE;
|
||||
filename = bfd_set_filename (abfd, ap->printable_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Forge a uniq id. */
|
||||
const size_t namelen = 2 + 8 + 1 + 2 + 8 + 1;
|
||||
filename = bfd_malloc (namelen);
|
||||
if (filename == NULL)
|
||||
return FALSE;
|
||||
snprintf (filename, namelen, "0x%lx-0x%lx",
|
||||
char buf[2 + 8 + 1 + 2 + 8 + 1];
|
||||
snprintf (buf, sizeof (buf), "0x%lx-0x%lx",
|
||||
entry->cputype, entry->cpusubtype);
|
||||
filename = bfd_set_filename (abfd, buf);
|
||||
}
|
||||
bfd_set_filename (abfd, filename);
|
||||
if (!filename)
|
||||
return FALSE;
|
||||
|
||||
areltdata = bfd_zmalloc (sizeof (struct areltdata));
|
||||
if (areltdata == NULL)
|
||||
|
38
bfd/opncls.c
38
bfd/opncls.c
@ -126,7 +126,6 @@ _bfd_delete_bfd (bfd *abfd)
|
||||
objalloc_free ((struct objalloc *) abfd->memory);
|
||||
}
|
||||
|
||||
free ((char *) bfd_get_filename (abfd));
|
||||
free (abfd->arelt_data);
|
||||
free (abfd);
|
||||
}
|
||||
@ -232,8 +231,7 @@ bfd_fopen (const char *filename, const char *target, const char *mode, int fd)
|
||||
|
||||
/* PR 11983: Do not cache the original filename, but
|
||||
rather make a copy - the original might go away. */
|
||||
nbfd->filename = bfd_strdup (filename);
|
||||
if (nbfd->filename == NULL)
|
||||
if (!bfd_set_filename (nbfd, filename))
|
||||
{
|
||||
fclose (nbfd->iostream);
|
||||
_bfd_delete_bfd (nbfd);
|
||||
@ -406,8 +404,7 @@ bfd_openstreamr (const char *filename, const char *target, void *streamarg)
|
||||
nbfd->iostream = stream;
|
||||
/* PR 11983: Do not cache the original filename, but
|
||||
rather make a copy - the original might go away. */
|
||||
nbfd->filename = bfd_strdup (filename);
|
||||
if (nbfd->filename == NULL)
|
||||
if (!bfd_set_filename (nbfd, filename))
|
||||
{
|
||||
_bfd_delete_bfd (nbfd);
|
||||
return NULL;
|
||||
@ -607,8 +604,7 @@ bfd_openr_iovec (const char *filename, const char *target,
|
||||
|
||||
/* PR 11983: Do not cache the original filename, but
|
||||
rather make a copy - the original might go away. */
|
||||
nbfd->filename = bfd_strdup (filename);
|
||||
if (nbfd->filename == NULL)
|
||||
if (!bfd_set_filename (nbfd, filename))
|
||||
{
|
||||
_bfd_delete_bfd (nbfd);
|
||||
return NULL;
|
||||
@ -679,8 +675,7 @@ bfd_openw (const char *filename, const char *target)
|
||||
|
||||
/* PR 11983: Do not cache the original filename, but
|
||||
rather make a copy - the original might go away. */
|
||||
nbfd->filename = bfd_strdup (filename);
|
||||
if (nbfd->filename == NULL)
|
||||
if (!bfd_set_filename (nbfd, filename))
|
||||
{
|
||||
_bfd_delete_bfd (nbfd);
|
||||
return NULL;
|
||||
@ -824,8 +819,7 @@ bfd_create (const char *filename, bfd *templ)
|
||||
return NULL;
|
||||
/* PR 11983: Do not cache the original filename, but
|
||||
rather make a copy - the original might go away. */
|
||||
nbfd->filename = bfd_strdup (filename);
|
||||
if (nbfd->filename == NULL)
|
||||
if (!bfd_set_filename (nbfd, filename))
|
||||
{
|
||||
_bfd_delete_bfd (nbfd);
|
||||
return NULL;
|
||||
@ -2040,17 +2034,23 @@ FUNCTION
|
||||
bfd_set_filename
|
||||
|
||||
SYNOPSIS
|
||||
void bfd_set_filename (bfd *abfd, char *filename);
|
||||
const char *bfd_set_filename (bfd *abfd, const char *filename);
|
||||
|
||||
DESCRIPTION
|
||||
Set the filename of @var{abfd}. The old filename, if any, is freed.
|
||||
@var{filename} must be allocated using @code{xmalloc}. After
|
||||
this call, it is owned @var{abfd}.
|
||||
Set the filename of @var{abfd}, copying the FILENAME parameter to
|
||||
bfd_alloc'd memory owned by @var{abfd}. Returns a pointer the
|
||||
newly allocated name, or NULL if the allocation failed.
|
||||
*/
|
||||
|
||||
void
|
||||
bfd_set_filename (bfd *abfd, char *filename)
|
||||
const char *
|
||||
bfd_set_filename (bfd *abfd, const char *filename)
|
||||
{
|
||||
free ((char *) abfd->filename);
|
||||
abfd->filename = filename;
|
||||
size_t len = strlen (filename) + 1;
|
||||
char *n = bfd_alloc (abfd, len);
|
||||
if (n)
|
||||
{
|
||||
memcpy (n, filename, len);
|
||||
abfd->filename = n;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
@ -1452,6 +1452,12 @@ _bfd_vms_lib_get_module (bfd *abfd, unsigned int modidx)
|
||||
break;
|
||||
}
|
||||
bfd_set_filename (res, newname);
|
||||
free (newname);
|
||||
if (bfd_get_filename (res) == NULL)
|
||||
{
|
||||
bfd_close (res);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tdata->cache[modidx] = res;
|
||||
|
||||
|
@ -1,3 +1,15 @@
|
||||
2020-05-20 Alan Modra <amodra@gmail.com>
|
||||
|
||||
PR 25993
|
||||
* solib-darwin.c (darwin_bfd_open): Don't strdup pathname for
|
||||
bfd_set_filename.
|
||||
* solib-aix.c (solib_aix_bfd_open): Use std::string for name
|
||||
passed to bfd_set_filename.
|
||||
* symfile-mem.c (add_vsyscall_page): Likewise for string
|
||||
passed to symbol_file_add_from_memory.
|
||||
(symbol_file_add_from_memory): Make name param a const char* and
|
||||
don't strdup.
|
||||
|
||||
2020-05-20 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* coff-pe-read.c (read_pe_exported_syms): Use bfd_get_filename
|
||||
|
@ -637,10 +637,10 @@ solib_aix_bfd_open (const char *pathname)
|
||||
along with appended parenthesized member name in order to allow commands
|
||||
listing all shared libraries to display. Otherwise, we would only be
|
||||
displaying the name of the archive member object. */
|
||||
bfd_set_filename (object_bfd.get (),
|
||||
xstrprintf ("%s%s",
|
||||
bfd_get_filename (archive_bfd.get ()),
|
||||
sep));
|
||||
std::string fname = string_printf ("%s%s",
|
||||
bfd_get_filename (archive_bfd.get ()),
|
||||
sep);
|
||||
bfd_set_filename (object_bfd.get (), fname.c_str ());
|
||||
|
||||
return object_bfd;
|
||||
}
|
||||
|
@ -662,7 +662,7 @@ darwin_bfd_open (const char *pathname)
|
||||
/* The current filename for fat-binary BFDs is a name generated
|
||||
by BFD, usually a string containing the name of the architecture.
|
||||
Reset its value to the actual filename. */
|
||||
bfd_set_filename (res.get (), xstrdup (pathname));
|
||||
bfd_set_filename (res.get (), pathname);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -78,11 +78,10 @@ target_read_memory_bfd (bfd_vma memaddr, bfd_byte *myaddr, bfd_size_type len)
|
||||
and read its in-core symbols out of inferior memory. SIZE, if
|
||||
non-zero, is the known size of the object. TEMPL is a bfd
|
||||
representing the target's format. NAME is the name to use for this
|
||||
symbol file in messages; it can be NULL or a malloc-allocated string
|
||||
which will be attached to the BFD. */
|
||||
symbol file in messages; it can be NULL. */
|
||||
static struct objfile *
|
||||
symbol_file_add_from_memory (struct bfd *templ, CORE_ADDR addr,
|
||||
size_t size, char *name, int from_tty)
|
||||
size_t size, const char *name, int from_tty)
|
||||
{
|
||||
struct objfile *objf;
|
||||
struct bfd *nbfd;
|
||||
@ -102,7 +101,7 @@ symbol_file_add_from_memory (struct bfd *templ, CORE_ADDR addr,
|
||||
gdb_bfd_ref_ptr nbfd_holder = gdb_bfd_ref_ptr::new_reference (nbfd);
|
||||
|
||||
if (name == NULL)
|
||||
name = xstrdup ("shared object read from target memory");
|
||||
name = "shared object read from target memory";
|
||||
bfd_set_filename (nbfd, name);
|
||||
|
||||
if (!bfd_check_format (nbfd, bfd_object))
|
||||
@ -183,8 +182,9 @@ add_vsyscall_page (struct target_ops *target, int from_tty)
|
||||
return;
|
||||
}
|
||||
|
||||
char *name = xstrprintf ("system-supplied DSO at %s",
|
||||
paddress (target_gdbarch (), vsyscall_range.start));
|
||||
std::string name = string_printf ("system-supplied DSO at %s",
|
||||
paddress (target_gdbarch (),
|
||||
vsyscall_range.start));
|
||||
try
|
||||
{
|
||||
/* Pass zero for FROM_TTY, because the action of loading the
|
||||
@ -193,7 +193,7 @@ add_vsyscall_page (struct target_ops *target, int from_tty)
|
||||
symbol_file_add_from_memory (bfd,
|
||||
vsyscall_range.start,
|
||||
vsyscall_range.length,
|
||||
name,
|
||||
name.c_str (),
|
||||
0 /* from_tty */);
|
||||
}
|
||||
catch (const gdb_exception &ex)
|
||||
|
@ -1,3 +1,12 @@
|
||||
2020-05-20 Alan Modra <amodra@gmail.com>
|
||||
|
||||
PR 25993
|
||||
* emultempl/pe.em (gld_${EMULATION_NAME}_after_open): Don't copy
|
||||
other_bfd_filename for bfd_set_filename, and test result of
|
||||
bfd_set_filename call. Don't create a new is->filename, simply
|
||||
copy from bfd filename. Free new_name after bfd_set_filename.
|
||||
* emultempl/pep.em (gld_${EMULATION_NAME}_after_open): Likewise.
|
||||
|
||||
2020-05-19 Siddhesh Poyarekar <siddesh.poyarekar@arm.com>
|
||||
|
||||
* testsuite/ld-aarch64/aarch64-elf.exp: New test
|
||||
|
@ -1523,7 +1523,6 @@ gld_${EMULATION_NAME}_after_open (void)
|
||||
struct bfd_symbol *s;
|
||||
struct bfd_link_hash_entry * blhe;
|
||||
const char *other_bfd_filename;
|
||||
char *n;
|
||||
|
||||
s = (relocs[i]->sym_ptr_ptr)[0];
|
||||
|
||||
@ -1550,9 +1549,9 @@ gld_${EMULATION_NAME}_after_open (void)
|
||||
continue;
|
||||
|
||||
/* Rename this implib to match the other one. */
|
||||
n = xmalloc (strlen (other_bfd_filename) + 1);
|
||||
strcpy (n, other_bfd_filename);
|
||||
bfd_set_filename (is->the_bfd->my_archive, n);
|
||||
if (!bfd_set_filename (is->the_bfd->my_archive,
|
||||
other_bfd_filename))
|
||||
einfo ("%F%P: %pB: %E\n", is->the_bfd);
|
||||
}
|
||||
|
||||
free (relocs);
|
||||
@ -1655,28 +1654,14 @@ gld_${EMULATION_NAME}_after_open (void)
|
||||
else /* sentinel */
|
||||
seq = 'c';
|
||||
|
||||
/* PR 25993: It is possible that is->the_bfd-filename == is->filename.
|
||||
In which case calling bfd_set_filename on one will free the memory
|
||||
pointed to by the other. */
|
||||
if (is->filename == bfd_get_filename (is->the_bfd))
|
||||
{
|
||||
new_name = xmalloc (strlen (is->filename) + 3);
|
||||
sprintf (new_name, "%s.%c", is->filename, seq);
|
||||
bfd_set_filename (is->the_bfd, new_name);
|
||||
is->filename = new_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_name
|
||||
= xmalloc (strlen (bfd_get_filename (is->the_bfd)) + 3);
|
||||
sprintf (new_name, "%s.%c",
|
||||
bfd_get_filename (is->the_bfd), seq);
|
||||
bfd_set_filename (is->the_bfd, new_name);
|
||||
|
||||
new_name = xmalloc (strlen (is->filename) + 3);
|
||||
sprintf (new_name, "%s.%c", is->filename, seq);
|
||||
is->filename = new_name;
|
||||
}
|
||||
new_name
|
||||
= xmalloc (strlen (bfd_get_filename (is->the_bfd)) + 3);
|
||||
sprintf (new_name, "%s.%c",
|
||||
bfd_get_filename (is->the_bfd), seq);
|
||||
is->filename = bfd_set_filename (is->the_bfd, new_name);
|
||||
free (new_name);
|
||||
if (!is->filename)
|
||||
einfo ("%F%P: %pB: %E\n", is->the_bfd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1491,7 +1491,6 @@ gld_${EMULATION_NAME}_after_open (void)
|
||||
struct bfd_symbol *s;
|
||||
struct bfd_link_hash_entry * blhe;
|
||||
const char *other_bfd_filename;
|
||||
char *n;
|
||||
|
||||
s = (relocs[i]->sym_ptr_ptr)[0];
|
||||
|
||||
@ -1518,9 +1517,9 @@ gld_${EMULATION_NAME}_after_open (void)
|
||||
continue;
|
||||
|
||||
/* Rename this implib to match the other one. */
|
||||
n = xmalloc (strlen (other_bfd_filename) + 1);
|
||||
strcpy (n, other_bfd_filename);
|
||||
bfd_set_filename (is->the_bfd->my_archive, n);
|
||||
if (!bfd_set_filename (is->the_bfd->my_archive,
|
||||
other_bfd_filename))
|
||||
einfo ("%F%P: %pB: %E\n", is->the_bfd);
|
||||
}
|
||||
|
||||
free (relocs);
|
||||
@ -1623,28 +1622,14 @@ gld_${EMULATION_NAME}_after_open (void)
|
||||
else /* sentinel */
|
||||
seq = 'c';
|
||||
|
||||
/* PR 25993: It is possible that is->the_bfd-filename == is->filename.
|
||||
In which case calling bfd_set_filename on one will free the memory
|
||||
pointed to by the other. */
|
||||
if (is->filename == bfd_get_filename (is->the_bfd))
|
||||
{
|
||||
new_name = xmalloc (strlen (is->filename) + 3);
|
||||
sprintf (new_name, "%s.%c", is->filename, seq);
|
||||
bfd_set_filename (is->the_bfd, new_name);
|
||||
is->filename = new_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_name
|
||||
= xmalloc (strlen (bfd_get_filename (is->the_bfd)) + 3);
|
||||
sprintf (new_name, "%s.%c",
|
||||
bfd_get_filename (is->the_bfd), seq);
|
||||
bfd_set_filename (is->the_bfd, new_name);
|
||||
|
||||
new_name = xmalloc (strlen (is->filename) + 3);
|
||||
sprintf (new_name, "%s.%c", is->filename, seq);
|
||||
is->filename = new_name;
|
||||
}
|
||||
new_name
|
||||
= xmalloc (strlen (bfd_get_filename (is->the_bfd)) + 3);
|
||||
sprintf (new_name, "%s.%c",
|
||||
bfd_get_filename (is->the_bfd), seq);
|
||||
is->filename = bfd_set_filename (is->the_bfd, new_name);
|
||||
free (new_name);
|
||||
if (!is->filename)
|
||||
einfo ("%F%P: %pB: %E\n", is->the_bfd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user