On Mon, Feb 9, 2026 at 2:56 PM LIU Hao <[email protected]> wrote:
>
> 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

LGTM, please leave others some time to comment.

Thanks,
Richard.

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

Reply via email to