[binutils-gdb] libiberty: Preserve `errno` across calls to `libiberty_vprintf_buffer_size()`
Alan Modra via Binutils-cvs <[email protected]>
| Newsgroups | gmane.comp.gnu.binutils.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=f13dc4efd3c7feca303a139f1d9feea128fb1d03 commit f13dc4efd3c7feca303a139f1d9feea128fb1d03 Author: LIU Hao <[email protected]> Date: Mon Feb 9 21:44:07 2026 +0800 libiberty: Preserve `errno` across calls to `libiberty_vprintf_buffer_size()` The MSVCRT `strtoul()` function resets `errno` to zero upon success. On such a system, `libiberty_vprintf_buffer_size()` could clobber `errno` like this: MINGW64 ~ $ ld nonexistent.file C:\MSYS64\mingw64\bin\ld.exe: cannot find nonexistent.file: No error libiberty/ChangeLog: * vprintf-support.c (do_strtoul): New function. (libiberty_vprintf_buffer_size): Replace `strtoul` with `do_strtoul`. Signed-off-by: LIU Hao <[email protected]> Diff: --- libiberty/vprintf-support.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/libiberty/vprintf-support.c b/libiberty/vprintf-support.c index 5a998fbf4ae..905e86b0437 100644 --- a/libiberty/vprintf-support.c +++ b/libiberty/vprintf-support.c @@ -27,6 +27,7 @@ Floor, Boston, MA 02110-1301, USA. */ # define va_copy(d,s) __va_copy((d),(s)) #endif #include <stdio.h> +#include <errno.h> #ifdef HAVE_STRING_H #include <string.h> #endif @@ -37,6 +38,21 @@ extern unsigned long strtoul (); #endif #include "libiberty.h" +static inline unsigned long +do_strtoul (const char *str, char **endptr, int base) + { +#ifdef _WIN32 + /* The MSVCRT `strtoul()` function resets `errno` to zero upon success. + We must preserve it across this call. */ + int saved_errno = errno; +#endif + long value = strtoul (str, endptr, base); +#ifdef _WIN32 + errno = saved_errno; +#endif + return value; + } + int libiberty_vprintf_buffer_size (const char *format, va_list args) { @@ -65,7 +81,7 @@ libiberty_vprintf_buffer_size (const char *format, va_list args) total_width += abs (va_arg (ap, int)); } else - total_width += strtoul (p, (char **) &p, 10); + total_width += do_strtoul (p, (char **) &p, 10); if (*p == '.') { ++p; @@ -75,7 +91,7 @@ libiberty_vprintf_buffer_size (const char *format, va_list args) total_width += abs (va_arg (ap, int)); } else - total_width += strtoul (p, (char **) &p, 10); + total_width += do_strtoul (p, (char **) &p, 10); } do {