]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libiberty: Preserve `errno` across calls to `libiberty_vprintf_buffer_size()`
authorLIU Hao <lh_mouse@126.com>
Mon, 9 Feb 2026 13:44:07 +0000 (21:44 +0800)
committerJonathan Yong <10walls@gmail.com>
Thu, 12 Feb 2026 15:23:12 +0000 (15:23 +0000)
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>
libiberty/vprintf-support.c

index 5a998fbf4ae09b8932e442679873c6b972d863b7..905e86b0437ca0300408887191c2d9b25568f3cc 100644 (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
            {