[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
 	    {
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.