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>
This commit is contained in:
LIU Hao
2026-02-09 21:44:07 +08:00
committed by Jonathan Yong
parent 2fb61a5031
commit 25c18a03de

View File

@@ -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
{