The MSVCRT `strtoul()` function resets `errno` to zero upon success. On such a system, `libiberty_vprintf_buffer_size()` can 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]>
---
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 5a998fbf4ae0..905e86b0437c 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
{
--
2.53.0
From c46c0aa863f6e880de1fb861c05e9f18621ba38e Mon Sep 17 00:00:00 2001 From: LIU Hao <[email protected]> Date: Mon, 9 Feb 2026 21:44:07 +0800 Subject: [PATCH] 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]> --- 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 5a998fbf4ae0..905e86b0437c 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 { -- 2.53.0
OpenPGP_signature.asc
Description: OpenPGP digital signature
