The branch stable/13 has been updated by des:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=3053d32194fa74809235b71c0889b11a6a5f316c

commit 3053d32194fa74809235b71c0889b11a6a5f316c
Author:     Dag-Erling Smørgrav <d...@freebsd.org>
AuthorDate: 2024-09-20 16:30:30 +0000
Commit:     Dag-Erling Smørgrav <d...@freebsd.org>
CommitDate: 2024-10-06 09:17:14 +0000

    printf(): Save errno earlier.
    
    The manual page says %m is replaced with “the string representation of
    the error code stored in the errno variable at the beginning of the
    call”.  However, we don't actually save `errno` until fairly late in
    `__vfprintf()`.  Make sure it is saved before we do anything that
    might perturb `errno`.
    
    MFC after:      1 week
    Reviewed by:    kevans
    Differential Revision:  https://reviews.freebsd.org/D46718
    
    (cherry picked from commit 74f1007fcc838501c74a633792c3f01833bf65e1)
---
 lib/libc/stdio/local.h     |  2 +-
 lib/libc/stdio/snprintf.c  | 14 ++++++++------
 lib/libc/stdio/vasprintf.c |  5 +++--
 lib/libc/stdio/vdprintf.c  |  3 ++-
 lib/libc/stdio/vfprintf.c  | 20 ++++++++++----------
 lib/libc/stdio/vsnprintf.c |  7 ++++---
 lib/libc/stdio/vsprintf.c  | 10 ++++++----
 7 files changed, 34 insertions(+), 27 deletions(-)

diff --git a/lib/libc/stdio/local.h b/lib/libc/stdio/local.h
index a5c465bcdcba..cbc0d29ff823 100644
--- a/lib/libc/stdio/local.h
+++ b/lib/libc/stdio/local.h
@@ -80,7 +80,7 @@ extern int    __swsetup(FILE *);
 extern int     __sflags(const char *, int *);
 extern int     __ungetc(int, FILE *);
 extern wint_t  __ungetwc(wint_t, FILE *, locale_t);
-extern int     __vfprintf(FILE *, locale_t, const char *, __va_list);
+extern int     __vfprintf(FILE *, locale_t, int, const char *, __va_list);
 extern int     __vfscanf(FILE *, const char *, __va_list);
 extern int     __vfwprintf(FILE *, locale_t, const wchar_t *, __va_list);
 extern int     __vfwscanf(FILE * __restrict, locale_t, const wchar_t * 
__restrict,
diff --git a/lib/libc/stdio/snprintf.c b/lib/libc/stdio/snprintf.c
index 45a9e3d7d622..10889715e111 100644
--- a/lib/libc/stdio/snprintf.c
+++ b/lib/libc/stdio/snprintf.c
@@ -52,10 +52,11 @@ static char sccsid[] = "@(#)snprintf.c      8.1 (Berkeley) 
6/4/93";
 int
 snprintf(char * __restrict str, size_t n, char const * __restrict fmt, ...)
 {
+       FILE f = FAKE_FILE;
+       va_list ap;
        size_t on;
+       int serrno = errno;
        int ret;
-       va_list ap;
-       FILE f = FAKE_FILE;
 
        on = n;
        if (n != 0)
@@ -69,7 +70,7 @@ snprintf(char * __restrict str, size_t n, char const * 
__restrict fmt, ...)
        f._flags = __SWR | __SSTR;
        f._bf._base = f._p = (unsigned char *)str;
        f._bf._size = f._w = n;
-       ret = __vfprintf(&f, __get_locale(), fmt, ap);
+       ret = __vfprintf(&f, __get_locale(), serrno, fmt, ap);
        if (on > 0)
                *f._p = '\0';
        va_end(ap);
@@ -79,10 +80,11 @@ int
 snprintf_l(char * __restrict str, size_t n, locale_t locale,
                char const * __restrict fmt, ...)
 {
+       FILE f = FAKE_FILE;
+       va_list ap;
        size_t on;
+       int serrno = errno;
        int ret;
-       va_list ap;
-       FILE f = FAKE_FILE;
        FIX_LOCALE(locale);
 
        on = n;
@@ -97,7 +99,7 @@ snprintf_l(char * __restrict str, size_t n, locale_t locale,
        f._flags = __SWR | __SSTR;
        f._bf._base = f._p = (unsigned char *)str;
        f._bf._size = f._w = n;
-       ret = __vfprintf(&f, locale, fmt, ap);
+       ret = __vfprintf(&f, locale, serrno, fmt, ap);
        if (on > 0)
                *f._p = '\0';
        va_end(ap);
diff --git a/lib/libc/stdio/vasprintf.c b/lib/libc/stdio/vasprintf.c
index 2e5f8dd4107a..91748861829d 100644
--- a/lib/libc/stdio/vasprintf.c
+++ b/lib/libc/stdio/vasprintf.c
@@ -35,9 +35,9 @@
  */
 
 #include <sys/cdefs.h>
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <errno.h>
 #include "xlocale_private.h"
 #include "local.h"
 
@@ -45,6 +45,7 @@ int
 vasprintf_l(char **str, locale_t locale, const char *fmt, __va_list ap)
 {
        FILE f = FAKE_FILE;
+       int serrno = errno;
        int ret;
        FIX_LOCALE(locale);
 
@@ -56,7 +57,7 @@ vasprintf_l(char **str, locale_t locale, const char *fmt, 
__va_list ap)
                return (-1);
        }
        f._bf._size = f._w = 127;               /* Leave room for the NUL */
-       ret = __vfprintf(&f, locale, fmt, ap);
+       ret = __vfprintf(&f, locale, serrno, fmt, ap);
        if (ret < 0) {
                free(f._bf._base);
                *str = NULL;
diff --git a/lib/libc/stdio/vdprintf.c b/lib/libc/stdio/vdprintf.c
index a84efaa14b4d..3d0598613b82 100644
--- a/lib/libc/stdio/vdprintf.c
+++ b/lib/libc/stdio/vdprintf.c
@@ -47,6 +47,7 @@ vdprintf(int fd, const char * __restrict fmt, va_list ap)
 {
        FILE f = FAKE_FILE;
        unsigned char buf[BUFSIZ];
+       int serrno = errno;
        int ret;
 
        if (fd > SHRT_MAX) {
@@ -63,7 +64,7 @@ vdprintf(int fd, const char * __restrict fmt, va_list ap)
        f._bf._base = buf;
        f._bf._size = sizeof(buf);
 
-       if ((ret = __vfprintf(&f, __get_locale(), fmt, ap)) < 0)
+       if ((ret = __vfprintf(&f, __get_locale(), serrno, fmt, ap)) < 0)
                return (ret);
 
        return (__fflush(&f) ? EOF : ret);
diff --git a/lib/libc/stdio/vfprintf.c b/lib/libc/stdio/vfprintf.c
index e656a2707d3a..8cc4001a93cd 100644
--- a/lib/libc/stdio/vfprintf.c
+++ b/lib/libc/stdio/vfprintf.c
@@ -72,7 +72,8 @@ static char sccsid[] = "@(#)vfprintf.c        8.1 (Berkeley) 
6/4/93";
 #include "printflocal.h"
 
 static int     __sprint(FILE *, struct __suio *, locale_t);
-static int     __sbprintf(FILE *, locale_t, const char *, va_list) 
__printflike(3, 0)
+static int     __sbprintf(FILE *, locale_t, int, const char *, va_list)
+       __printflike(4, 0)
        __noinline;
 static char    *__wcsconv(wchar_t *, int);
 
@@ -173,7 +174,7 @@ __sprint(FILE *fp, struct __suio *uio, locale_t locale)
  * worries about ungetc buffers and so forth.
  */
 static int
-__sbprintf(FILE *fp, locale_t locale, const char *fmt, va_list ap)
+__sbprintf(FILE *fp, locale_t locale, int serrno, const char *fmt, va_list ap)
 {
        int ret;
        FILE fake = FAKE_FILE;
@@ -197,7 +198,7 @@ __sbprintf(FILE *fp, locale_t locale, const char *fmt, 
va_list ap)
        fake._lbfsize = 0;      /* not actually used, but Just In Case */
 
        /* do the work, then copy any error status */
-       ret = __vfprintf(&fake, locale, fmt, ap);
+       ret = __vfprintf(&fake, locale, serrno, fmt, ap);
        if (ret >= 0 && __fflush(&fake))
                ret = EOF;
        if (fake._flags & __SERR)
@@ -269,8 +270,9 @@ __wcsconv(wchar_t *wcsarg, int prec)
  */
 int
 vfprintf_l(FILE * __restrict fp, locale_t locale, const char * __restrict fmt0,
-               va_list ap)
+    va_list ap)
 {
+       int serrno = errno;
        int ret;
        FIX_LOCALE(locale);
 
@@ -278,9 +280,9 @@ vfprintf_l(FILE * __restrict fp, locale_t locale, const 
char * __restrict fmt0,
        /* optimise fprintf(stderr) (and other unbuffered Unix files) */
        if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
            fp->_file >= 0)
-               ret = __sbprintf(fp, locale, fmt0, ap);
+               ret = __sbprintf(fp, locale, serrno, fmt0, ap);
        else
-               ret = __vfprintf(fp, locale, fmt0, ap);
+               ret = __vfprintf(fp, locale, serrno, fmt0, ap);
        FUNLOCKFILE_CANCELSAFE();
        return (ret);
 }
@@ -305,7 +307,7 @@ vfprintf(FILE * __restrict fp, const char * __restrict 
fmt0, va_list ap)
  * Non-MT-safe version
  */
 int
-__vfprintf(FILE *fp, locale_t locale, const char *fmt0, va_list ap)
+__vfprintf(FILE *fp, locale_t locale, int serrno, const char *fmt0, va_list ap)
 {
        char *fmt;              /* format string */
        int ch;                 /* character from fmt */
@@ -315,7 +317,6 @@ __vfprintf(FILE *fp, locale_t locale, const char *fmt0, 
va_list ap)
        int ret;                /* return value accumulator */
        int width;              /* width from format (%8d), or 0 */
        int prec;               /* precision from format; <0 for N/A */
-       int saved_errno;
        int error;
        char errnomsg[NL_TEXTMAX];
        char sign;              /* sign prefix (' ', '+', '-', or \0) */
@@ -467,7 +468,6 @@ __vfprintf(FILE *fp, locale_t locale, const char *fmt0, 
va_list ap)
        savserr = fp->_flags & __SERR;
        fp->_flags &= ~__SERR;
 
-       saved_errno = errno;
        convbuf = NULL;
        fmt = (char *)fmt0;
        argtable = NULL;
@@ -779,7 +779,7 @@ fp_common:
                        break;
 #endif /* !NO_FLOATING_POINT */
                case 'm':
-                       error = __strerror_rl(saved_errno, errnomsg,
+                       error = __strerror_rl(serrno, errnomsg,
                            sizeof(errnomsg), locale);
                        cp = error == 0 ? errnomsg : "<strerror failure>";
                        size = (prec >= 0) ? strnlen(cp, prec) : strlen(cp);
diff --git a/lib/libc/stdio/vsnprintf.c b/lib/libc/stdio/vsnprintf.c
index 8fc7f9fdf725..1b00e9916506 100644
--- a/lib/libc/stdio/vsnprintf.c
+++ b/lib/libc/stdio/vsnprintf.c
@@ -49,12 +49,13 @@ static char sccsid[] = "@(#)vsnprintf.c     8.1 (Berkeley) 
6/4/93";
 
 int
 vsnprintf_l(char * __restrict str, size_t n, locale_t locale, 
-               const char * __restrict fmt, __va_list ap)
+    const char * __restrict fmt, __va_list ap)
 {
+       FILE f = FAKE_FILE;
        size_t on;
+       int serrno = errno;
        int ret;
        char dummy[2];
-       FILE f = FAKE_FILE;
        FIX_LOCALE(locale);
 
        on = n;
@@ -75,7 +76,7 @@ vsnprintf_l(char * __restrict str, size_t n, locale_t locale,
        f._flags = __SWR | __SSTR;
        f._bf._base = f._p = (unsigned char *)str;
        f._bf._size = f._w = n;
-       ret = __vfprintf(&f, locale, fmt, ap);
+       ret = __vfprintf(&f, locale, serrno, fmt, ap);
        if (on > 0)
                *f._p = '\0';
        return (ret);
diff --git a/lib/libc/stdio/vsprintf.c b/lib/libc/stdio/vsprintf.c
index 68a2f70469f4..4035fc12125a 100644
--- a/lib/libc/stdio/vsprintf.c
+++ b/lib/libc/stdio/vsprintf.c
@@ -41,23 +41,25 @@
 static char sccsid[] = "@(#)vsprintf.c 8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
-#include <stdio.h>
+#include <errno.h>
 #include <limits.h>
+#include <stdio.h>
 #include "local.h"
 #include "xlocale_private.h"
 
 int
 vsprintf_l(char * __restrict str, locale_t locale,
-               const char * __restrict fmt, __va_list ap)
+    const char * __restrict fmt, __va_list ap)
 {
-       int ret;
        FILE f = FAKE_FILE;
+       int serrno = errno;
+       int ret;
        FIX_LOCALE(locale);
 
        f._flags = __SWR | __SSTR;
        f._bf._base = f._p = (unsigned char *)str;
        f._bf._size = f._w = INT_MAX;
-       ret = __vfprintf(&f, locale, fmt, ap);
+       ret = __vfprintf(&f, locale, serrno, fmt, ap);
        *f._p = 0;
        return (ret);
 }

Reply via email to