diff options
author | 2023-06-14 14:24:50 +0930 | |
---|---|---|
committer | 2023-06-14 14:24:50 +0930 | |
commit | 6f860418d556d4e5492b3da9e1a52e4b85a85f3e (patch) | |
tree | 7d8223edf575df45e809a9d2068b518ac67086d6 /bfd/bfd.c | |
parent | Re: bfd/elf.c strtab memory leak (diff) | |
download | binutils-gdb-6f860418d556d4e5492b3da9e1a52e4b85a85f3e.tar.gz binutils-gdb-6f860418d556d4e5492b3da9e1a52e4b85a85f3e.tar.bz2 binutils-gdb-6f860418d556d4e5492b3da9e1a52e4b85a85f3e.zip |
asprintf memory leaks
A number of backends want to return bfd_reloc_dangerous messaqes from
relocation special_function, and construct the message using asprintf.
Such messages are not freed anywhere, leading to small memory leaks
inside libbfd. To limit the leaks, I'd implemented a static buffer in
the ppc backends that was freed before use in asprintf output. This
patch extends that scheme to other backends using a shared static
buffer and goes further in freeing the buffer on any bfd_close.
The patch also fixes a few other cases where asprintf output was not
freed after use.
bfd/
* bfd.c (_input_error_msg): Make global and rename to..
(_bfd_error_buf): ..this.
(bfd_asprintf): New function.
(bfd_errmsg): Use bfd_asprintf.
* opncls.c (bfd_close_all_done): Free _buf_error_buf.
* elf32-arm.c (find_thumb_glue, find_arm_glue): Use bfd_asprintf.
* elf32-nios2.c (nios2_elf32_relocate_section): Likewise.
* elf32-ppc.c (ppc_elf_unhandled_reloc): Likewise.
* elf64-ppc.c (ppc64_elf_unhandled_reloc): Likewise.
* elfnn-riscv.c (riscv_resolve_pcrel_lo_relocs): Likewise.
(riscv_elf_relocate_section): Likewise.
* libbfd.h: Regenerate.
gas/
* read.c (read_end): Free current_name and current_label.
(do_s_func): Likewise on error path. strdup label.
ld/
* pe-dll.c (make_head, make_tail, make_one),
(make_singleton_name_thunk, make_import_fixup_entry),
(make_runtime_pseudo_reloc),
(pe_create_runtime_relocator_reference: Free oname after use.
Diffstat (limited to 'bfd/bfd.c')
-rw-r--r-- | bfd/bfd.c | 60 |
1 files changed, 48 insertions, 12 deletions
diff --git a/bfd/bfd.c b/bfd/bfd.c index 4ae73701ce1..804acabf621 100644 --- a/bfd/bfd.c +++ b/bfd/bfd.c @@ -700,12 +700,16 @@ CODE_FRAGMENT .} .bfd_error_type; . +INTERNAL +.{* A buffer that is freed on bfd_close. *} +.extern char *_bfd_error_buf; +. */ static bfd_error_type bfd_error; static bfd_error_type input_error; static bfd *input_bfd; -static char *input_error_msg; +char *_bfd_error_buf; const char *const bfd_errmsgs[] = { @@ -793,8 +797,8 @@ bfd_set_input_error (bfd *input, bfd_error_type error_tag) /* This is an error that occurred during bfd_close when writing an archive, but on one of the input files. */ bfd_error = bfd_error_on_input; - free (input_error_msg); - input_error_msg = NULL; + free (_bfd_error_buf); + _bfd_error_buf = NULL; input_bfd = input; input_error = error_tag; if (input_error >= bfd_error_on_input) @@ -822,12 +826,10 @@ bfd_errmsg (bfd_error_type error_tag) if (error_tag == bfd_error_on_input) { const char *msg = bfd_errmsg (input_error); - - free (input_error_msg); - input_error_msg = NULL; - if (asprintf (&input_error_msg, _(bfd_errmsgs [error_tag]), - bfd_get_filename (input_bfd), msg) != -1) - return input_error_msg; + char *ret = bfd_asprintf (_(bfd_errmsgs[error_tag]), + bfd_get_filename (input_bfd), msg); + if (ret) + return ret; /* Ick, what to do on out of memory? */ return msg; @@ -839,7 +841,7 @@ bfd_errmsg (bfd_error_type error_tag) if (error_tag > bfd_error_invalid_error_code) error_tag = bfd_error_invalid_error_code; /* sanity check */ - return _(bfd_errmsgs [error_tag]); + return _(bfd_errmsgs[error_tag]); } /* @@ -869,6 +871,40 @@ bfd_perror (const char *message) } /* +INTERNAL_FUNCTION + bfd_asprintf + +SYNOPSIS + char *bfd_asprintf (const char *fmt, ...); + +DESCRIPTION + Primarily for error reporting, this function is like + libiberty's xasprintf except that it can return NULL on no + memory and the returned string should not be freed. Uses a + single malloc'd buffer managed by libbfd, _bfd_error_buf. + Be aware that a call to this function frees the result of any + previous call. bfd_errmsg (bfd_error_on_input) also calls + this function. +*/ + +char * +bfd_asprintf (const char *fmt, ...) +{ + free (_bfd_error_buf); + _bfd_error_buf = NULL; + va_list ap; + va_start (ap, fmt); + int count = vasprintf (&_bfd_error_buf, fmt, ap); + va_end (ap); + if (count == -1) + { + bfd_set_error (bfd_error_no_memory); + _bfd_error_buf = NULL; + } + return _bfd_error_buf; +} + +/* SUBSECTION BFD error handler @@ -1663,8 +1699,8 @@ bfd_init (void) { bfd_error = bfd_error_no_error; input_bfd = NULL; - free (input_error_msg); - input_error_msg = NULL; + free (_bfd_error_buf); + _bfd_error_buf = NULL; input_error = bfd_error_no_error; _bfd_error_program_name = NULL; _bfd_error_internal = error_handler_fprintf; |