From: Alan Modra Date: Fri, 3 Jan 2025 23:10:21 +0000 (+1030) Subject: bfd_set_input_error X-Git-Tag: binutils-2_44~275 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d8d3ed295efb75a7421340484e3fe8115402b1f2;p=thirdparty%2Fbinutils-gdb.git bfd_set_input_error My recent change to closing archives showed some problems with the way we stash errors for archive elements. The most obvious thing found by oss-fuzz, is that if output archive elements are closed during bfd_close of an archive, then we can't access the element filename when printing the element. So change bfd_set_input_error to stash the entire error message instead of input bfd and input error. * bfd.c (input_bfd, input_error): Delete. (bfd_error, _bfd_error_buf): Move. (_bfd_clear_error_data): Move. Make static. Clear bfd_error too. (bfd_set_input_error): Print the error use bfd_asprintf here.. (bfd_errmsg): ..not here. (bfd_init): Update. * opncls.c (bfd_close_all_done): Don't call _bfd_clear_error_data. * libbfd.h: Regenerate. --- diff --git a/bfd/bfd.c b/bfd/bfd.c index 0e567ddeaea..194f24179fd 100644 --- a/bfd/bfd.c +++ b/bfd/bfd.c @@ -768,11 +768,6 @@ CODE_FRAGMENT . */ -static TLS bfd_error_type bfd_error; -static TLS bfd_error_type input_error; -static TLS bfd *input_bfd; -static TLS char *_bfd_error_buf; - const char *const bfd_errmsgs[] = { N_("no error"), @@ -800,6 +795,19 @@ const char *const bfd_errmsgs[] = N_("#") }; +static TLS bfd_error_type bfd_error; +static TLS char *_bfd_error_buf; + +/* Free any data associated with the BFD error. */ + +static void +_bfd_clear_error_data (void) +{ + bfd_error = bfd_error_no_error; + free (_bfd_error_buf); + _bfd_error_buf = NULL; +} + /* FUNCTION bfd_get_error @@ -858,12 +866,12 @@ 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; _bfd_clear_error_data (); - input_bfd = input; - input_error = error_tag; - if (input_error >= bfd_error_on_input) + if (error_tag >= bfd_error_on_input) abort (); + if (bfd_asprintf (_(bfd_errmsgs[bfd_error_on_input]), + bfd_get_filename (input), bfd_errmsg (error_tag))) + bfd_error = bfd_error_on_input; } /* @@ -885,16 +893,7 @@ bfd_errmsg (bfd_error_type error_tag) extern int errno; #endif if (error_tag == bfd_error_on_input) - { - const char *msg = bfd_errmsg (input_error); - 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; - } + return _bfd_error_buf; if (error_tag == bfd_error_system_call) return xstrerror (errno); @@ -931,24 +930,6 @@ bfd_perror (const char *message) fflush (stderr); } -/* -INTERNAL_FUNCTION - _bfd_clear_error_data - -SYNOPSIS - void _bfd_clear_error_data (void); - -DESCRIPTION - Free any data associated with the BFD error. -*/ - -void -_bfd_clear_error_data (void) -{ - free (_bfd_error_buf); - _bfd_error_buf = NULL; -} - /* INTERNAL_FUNCTION bfd_asprintf @@ -1961,10 +1942,7 @@ DESCRIPTION unsigned int bfd_init (void) { - bfd_error = bfd_error_no_error; - input_bfd = NULL; _bfd_clear_error_data (); - input_error = bfd_error_no_error; _bfd_error_internal = error_handler_fprintf; _bfd_assert_handler = _bfd_default_assert_handler; diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 3925fba00e4..f86cc23db45 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -963,8 +963,6 @@ bool bfd_write_bigendian_4byte_int (bfd *, unsigned int) ATTRIBUTE_HIDDEN; unsigned int bfd_log2 (bfd_vma x) ATTRIBUTE_HIDDEN; /* Extracted from bfd.c. */ -void _bfd_clear_error_data (void) ATTRIBUTE_HIDDEN; - char *bfd_asprintf (const char *fmt, ...) ATTRIBUTE_HIDDEN; /* Cached _bfd_check_format messages are put in this. */ diff --git a/bfd/opncls.c b/bfd/opncls.c index a0b30f568d7..93adbf117f0 100644 --- a/bfd/opncls.c +++ b/bfd/opncls.c @@ -943,7 +943,6 @@ bfd_close_all_done (bfd *abfd) _maybe_make_executable (abfd); _bfd_delete_bfd (abfd); - _bfd_clear_error_data (); return ret; }