[binutils-gdb] libiberty: Preserve `errno` across calls to `libiberty_vprintf_buffer_size()`
Alan Modra
amodra@sourceware.org
Sun Mar 8 22:04:54 GMT 2026
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=f13dc4efd3c7feca303a139f1d9feea128fb1d03
commit f13dc4efd3c7feca303a139f1d9feea128fb1d03
Author: LIU Hao <lh_mouse@126.com>
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 <lh_mouse@126.com>
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
{
More information about the Binutils-cvs
mailing list