aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2019-09-02 16:13:05 +0930
committerAlan Modra <amodra@gmail.com>2019-09-05 11:33:34 +0930
commit89bdc77eabf5ede68322f6e47e003c1dc45b9ccb (patch)
tree87e650254fe116fdf69906ca003a0d8c34c491ac
parentAutomatic date update in version.in (diff)
downloadbinutils-gdb-89bdc77eabf5ede68322f6e47e003c1dc45b9ccb.tar.gz
binutils-gdb-89bdc77eabf5ede68322f6e47e003c1dc45b9ccb.tar.bz2
binutils-gdb-89bdc77eabf5ede68322f6e47e003c1dc45b9ccb.zip
PR24955, libbfd terminating program on out of memory
This patch fixes the worst of the cases where libbfd might terminate a program due to calling xstrdup or xmalloc. I've also fixed some error paths that didn't clean up properly. PR 24955 * libbfd-in.h (bfd_strdup): New inline function. * archive.c (_bfd_get_elt_at_filepos): Use bfd_strdup. Close bfd on error. * elfcode.h (_bfd_elf_bfd_from_remote_memory): Use bfd_strdup. * opncls.c (bfd_fopen): Use bfd_strdup. Close fd and stream on error. (bfd_openstreamr): Use bfd_strdup. (bfd_openr_iovec, bfd_openw, bfd_create): Likewise. * plugin.c (try_load_plugin): Use bfd_malloc. * libbfd.h: Regenerate.
-rw-r--r--bfd/ChangeLog14
-rw-r--r--bfd/archive.c6
-rw-r--r--bfd/elfcode.h11
-rw-r--r--bfd/libbfd-in.h9
-rw-r--r--bfd/libbfd.h9
-rw-r--r--bfd/opncls.c41
-rw-r--r--bfd/plugin.c4
7 files changed, 85 insertions, 9 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index f033af74436..319ba5a5712 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,17 @@
+2019-09-05 Alan Modra <amodra@gmail.com>
+
+ PR 24955
+ * libbfd-in.h (bfd_strdup): New inline function.
+ * archive.c (_bfd_get_elt_at_filepos): Use bfd_strdup. Close
+ bfd on error.
+ * elfcode.h (_bfd_elf_bfd_from_remote_memory): Use bfd_strdup.
+ * opncls.c (bfd_fopen): Use bfd_strdup. Close fd and stream
+ on error.
+ (bfd_openstreamr): Use bfd_strdup.
+ (bfd_openr_iovec, bfd_openw, bfd_create): Likewise.
+ * plugin.c (try_load_plugin): Use bfd_malloc.
+ * libbfd.h: Regenerate.
+
2019-09-02 Alan Modra <amodra@gmail.com>
PR 11983
diff --git a/bfd/archive.c b/bfd/archive.c
index 690718e9494..ef71e8a7963 100644
--- a/bfd/archive.c
+++ b/bfd/archive.c
@@ -728,7 +728,9 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
else
{
n_bfd->origin = n_bfd->proxy_origin;
- n_bfd->filename = xstrdup (filename);
+ n_bfd->filename = bfd_strdup (filename);
+ if (n_bfd->filename == NULL)
+ goto out;
}
n_bfd->arelt_data = new_areldata;
@@ -745,8 +747,10 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
|| _bfd_add_bfd_to_archive_cache (archive, filepos, n_bfd))
return n_bfd;
+ out:
free (new_areldata);
n_bfd->arelt_data = NULL;
+ bfd_close (n_bfd);
return NULL;
}
diff --git a/bfd/elfcode.h b/bfd/elfcode.h
index 9a73c3b71f5..625ae993df6 100644
--- a/bfd/elfcode.h
+++ b/bfd/elfcode.h
@@ -1652,6 +1652,7 @@ NAME(_bfd_elf,bfd_from_remote_memory)
bfd_vma high_offset;
bfd_vma shdr_end;
bfd_vma loadbase;
+ char *filename;
/* Read in the ELF header in external format. */
err = target_read_memory (ehdr_vma, (bfd_byte *) &x_ehdr, sizeof x_ehdr);
@@ -1859,14 +1860,22 @@ 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)
{
+ free (filename);
free (bim);
free (contents);
return NULL;
}
- nbfd->filename = xstrdup ("<in-memory>");
+ nbfd->filename = filename;
nbfd->xvec = templ->xvec;
bim->size = high_offset;
bim->buffer = contents;
diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h
index 7a97dfae199..cac4d3b022e 100644
--- a/bfd/libbfd-in.h
+++ b/bfd/libbfd-in.h
@@ -123,6 +123,15 @@ extern void *bfd_realloc2
extern void *bfd_zmalloc2
(bfd_size_type, bfd_size_type) ATTRIBUTE_HIDDEN;
+static inline char *
+bfd_strdup (const char *str)
+{
+ size_t len = strlen (str) + 1;
+ char *buf = bfd_malloc (len);
+ if (buf != NULL)
+ memcpy (buf, str, len);
+ return buf;
+}
/* These routines allocate and free things on the BFD's objalloc. */
extern void *bfd_alloc2
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 13f4c5b4082..aabe247068e 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -128,6 +128,15 @@ extern void *bfd_realloc2
extern void *bfd_zmalloc2
(bfd_size_type, bfd_size_type) ATTRIBUTE_HIDDEN;
+static inline char *
+bfd_strdup (const char *str)
+{
+ size_t len = strlen (str) + 1;
+ char *buf = bfd_malloc (len);
+ if (buf != NULL)
+ memcpy (buf, str, len);
+ return buf;
+}
/* These routines allocate and free things on the BFD's objalloc. */
extern void *bfd_alloc2
diff --git a/bfd/opncls.c b/bfd/opncls.c
index b8cda411e60..07f89b9a4c1 100644
--- a/bfd/opncls.c
+++ b/bfd/opncls.c
@@ -223,6 +223,8 @@ bfd_fopen (const char *filename, const char *target, const char *mode, int fd)
if (nbfd->iostream == NULL)
{
bfd_set_error (bfd_error_system_call);
+ if (fd != -1)
+ close (fd);
_bfd_delete_bfd (nbfd);
return NULL;
}
@@ -231,7 +233,13 @@ 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 = xstrdup (filename);
+ nbfd->filename = bfd_strdup (filename);
+ if (nbfd->filename == NULL)
+ {
+ fclose (nbfd->iostream);
+ _bfd_delete_bfd (nbfd);
+ return NULL;
+ }
/* Figure out whether the user is opening the file for reading,
writing, or both, by looking at the MODE argument. */
@@ -243,8 +251,9 @@ bfd_fopen (const char *filename, const char *target, const char *mode, int fd)
else
nbfd->direction = write_direction;
- if (! bfd_cache_init (nbfd))
+ if (!bfd_cache_init (nbfd))
{
+ fclose (nbfd->iostream);
_bfd_delete_bfd (nbfd);
return NULL;
}
@@ -398,7 +407,12 @@ 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 = xstrdup (filename);
+ nbfd->filename = bfd_strdup (filename);
+ if (nbfd->filename == NULL)
+ {
+ _bfd_delete_bfd (nbfd);
+ return NULL;
+ }
nbfd->direction = read_direction;
if (! bfd_cache_init (nbfd))
@@ -594,7 +608,12 @@ 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 = xstrdup (filename);
+ nbfd->filename = bfd_strdup (filename);
+ if (nbfd->filename == NULL)
+ {
+ _bfd_delete_bfd (nbfd);
+ return NULL;
+ }
nbfd->direction = read_direction;
/* `open_p (...)' would get expanded by an the open(2) syscall macro. */
@@ -661,7 +680,12 @@ 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 = xstrdup (filename);
+ nbfd->filename = bfd_strdup (filename);
+ if (nbfd->filename == NULL)
+ {
+ _bfd_delete_bfd (nbfd);
+ return NULL;
+ }
nbfd->direction = write_direction;
if (bfd_open_file (nbfd) == NULL)
@@ -801,7 +825,12 @@ 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 = xstrdup (filename);
+ nbfd->filename = bfd_strdup (filename);
+ if (nbfd->filename == NULL)
+ {
+ _bfd_delete_bfd (nbfd);
+ return NULL;
+ }
if (templ)
nbfd->xvec = templ->xvec;
nbfd->direction = no_direction;
diff --git a/bfd/plugin.c b/bfd/plugin.c
index 376e92cdb3e..5f760e9c429 100644
--- a/bfd/plugin.c
+++ b/bfd/plugin.c
@@ -262,7 +262,9 @@ try_load_plugin (const char *pname, bfd *abfd, int *has_plugin_p)
}
}
- plugin_list_iter = (struct plugin_list_entry *) xmalloc (sizeof *plugin_list_iter);
+ plugin_list_iter = bfd_malloc (sizeof *plugin_list_iter);
+ if (plugin_list_iter == NULL)
+ return 0;
plugin_list_iter->handle = plugin_handle;
plugin_list_iter->claim_file = NULL;
plugin_list_iter->next = plugin_list;