Sync with OpenBSD.

This commit is contained in:
Todd C. Miller
2022-12-03 09:04:25 -07:00
parent 31152ba4d7
commit ee6420ad5b

View File

@@ -1,5 +1,5 @@
/* $OpenBSD: vfprintf.c,v 1.67 2014/12/21 00:23:30 daniel Exp $ */ /* $OpenBSD: vfprintf.c,v 1.67 2014/12/21 00:23:30 daniel Exp $ */
/* /*
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
* *
* Copyright (c) 1999-2005, 2008, 2010-2016 * Copyright (c) 1999-2005, 2008, 2010-2016
@@ -131,10 +131,8 @@ __wcsconv(wchar_t *wcsarg, int prec)
memset(&mbs, 0, sizeof(mbs)); memset(&mbs, 0, sizeof(mbs));
p = wcsarg; p = wcsarg;
nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs); nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs);
if (nbytes == (size_t)-1) { if (nbytes == (size_t)-1)
errno = EILSEQ;
return NULL; return NULL;
}
} else { } else {
/* /*
* Optimisation: if the output precision is small enough, * Optimisation: if the output precision is small enough,
@@ -154,10 +152,8 @@ __wcsconv(wchar_t *wcsarg, int prec)
break; break;
nbytes += clen; nbytes += clen;
} }
if (clen == (size_t)-1) { if (clen == (size_t)-1)
errno = EILSEQ;
return NULL; return NULL;
}
} }
} }
if ((convbuf = malloc(nbytes + 1)) == NULL) if ((convbuf = malloc(nbytes + 1)) == NULL)
@@ -169,7 +165,6 @@ __wcsconv(wchar_t *wcsarg, int prec)
if ((nbytes = wcsrtombs(convbuf, (const wchar_t **)&p, if ((nbytes = wcsrtombs(convbuf, (const wchar_t **)&p,
nbytes, &mbs)) == (size_t)-1) { nbytes, &mbs)) == (size_t)-1) {
free(convbuf); free(convbuf);
errno = EILSEQ;
return NULL; return NULL;
} }
convbuf[nbytes] = '\0'; convbuf[nbytes] = '\0';
@@ -233,7 +228,7 @@ xxxprintf(char **strp, size_t strsize, int alloc, const char *fmt0, va_list ap)
{ {
char *fmt; /* format string */ char *fmt; /* format string */
int ch; /* character from fmt */ int ch; /* character from fmt */
int n, n2; /* handy integers (short term usage) */ int n; /* handy integers (short term usage) */
char *cp; /* handy char pointer (short term usage) */ char *cp; /* handy char pointer (short term usage) */
int flags; /* flags as above */ int flags; /* flags as above */
int ret; /* return value accumulator */ int ret; /* return value accumulator */
@@ -308,6 +303,9 @@ xxxprintf(char **strp, size_t strsize, int alloc, const char *fmt0, va_list ap)
static const char xdigs_lower[16] = "0123456789abcdef"; static const char xdigs_lower[16] = "0123456789abcdef";
static const char xdigs_upper[16] = "0123456789ABCDEF"; static const char xdigs_upper[16] = "0123456789ABCDEF";
/*
* BEWARE, these `goto done' on error, and PAD uses `n'.
*/
/* Print chars to "str", (allocate as needed if alloc is set). */ /* Print chars to "str", (allocate as needed if alloc is set). */
#define PRINT(ptr, len) do { \ #define PRINT(ptr, len) do { \
const char *p = ptr; \ const char *p = ptr; \
@@ -330,7 +328,6 @@ xxxprintf(char **strp, size_t strsize, int alloc, const char *fmt0, va_list ap)
} \ } \
} while (0) } while (0)
/* BEWARE, PAD uses `n' and PRINTANDPAD uses `n2'. */
#define PAD(plen, pstr) do { \ #define PAD(plen, pstr) do { \
if ((n = (plen)) > 0) { \ if ((n = (plen)) > 0) { \
while (n > PADSIZE) { \ while (n > PADSIZE) { \
@@ -341,7 +338,7 @@ xxxprintf(char **strp, size_t strsize, int alloc, const char *fmt0, va_list ap)
} \ } \
} while (0) } while (0)
#define PRINTANDPAD(p, ep, len, with) do { \ #define PRINTANDPAD(p, ep, len, with) do { \
n2 = (ep) - (p); \ int n2 = (ep) - (p); \
if (n2 > (len)) \ if (n2 > (len)) \
n2 = (len); \ n2 = (len); \
if (n2 > 0) \ if (n2 > 0) \
@@ -388,8 +385,8 @@ xxxprintf(char **strp, size_t strsize, int alloc, const char *fmt0, va_list ap)
* Get * arguments, including the form *nn$. Preserve the nextarg * Get * arguments, including the form *nn$. Preserve the nextarg
* that the argument can be gotten once the type is determined. * that the argument can be gotten once the type is determined.
*/ */
#define GETASTER(val) \ #define GETASTER(val) do { \
n2 = 0; \ int n2 = 0; \
cp = fmt; \ cp = fmt; \
while (is_digit(*cp)) { \ while (is_digit(*cp)) { \
APPEND_DIGIT(n2, *cp); \ APPEND_DIGIT(n2, *cp); \
@@ -399,7 +396,10 @@ xxxprintf(char **strp, size_t strsize, int alloc, const char *fmt0, va_list ap)
int hold = nextarg; \ int hold = nextarg; \
if (argtable == NULL) { \ if (argtable == NULL) { \
argtable = statargtable; \ argtable = statargtable; \
__find_arguments(fmt0, orgap, &argtable); \ if (__find_arguments(fmt0, orgap, &argtable) == -1) { \
ret = -1; \
goto done; \
} \
} \ } \
nextarg = n2; \ nextarg = n2; \
val = GETARG(int); \ val = GETARG(int); \
@@ -407,7 +407,8 @@ xxxprintf(char **strp, size_t strsize, int alloc, const char *fmt0, va_list ap)
fmt = ++cp; \ fmt = ++cp; \
} else { \ } else { \
val = GETARG(int); \ val = GETARG(int); \
} } \
} while (0)
/* /*
* Get the argument indexed by nextarg. If the argument table is * Get the argument indexed by nextarg. If the argument table is
@@ -448,12 +449,14 @@ xxxprintf(char **strp, size_t strsize, int alloc, const char *fmt0, va_list ap)
*/ */
for (;;) { for (;;) {
for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
/* void */; continue;
if ((n = fmt - cp) != 0) {
if (n > INT_MAX - ret) if (fmt != cp) {
ptrdiff_t m = fmt - cp;
if (m < 0 || m > INT_MAX - ret)
goto overflow; goto overflow;
PRINT(cp, n); PRINT(cp, m);
ret += n; ret += m;
} }
if (ch == '\0') if (ch == '\0')
goto done; goto done;
@@ -518,8 +521,11 @@ reswitch: switch (ch) {
nextarg = n; nextarg = n;
if (argtable == NULL) { if (argtable == NULL) {
argtable = statargtable; argtable = statargtable;
__find_arguments(fmt0, orgap, if (__find_arguments(fmt0, orgap,
&argtable); &argtable) == -1) {
ret = -1;
goto done;
}
} }
goto rflag; goto rflag;
} }
@@ -544,8 +550,11 @@ reswitch: switch (ch) {
nextarg = n; nextarg = n;
if (argtable == NULL) { if (argtable == NULL) {
argtable = statargtable; argtable = statargtable;
__find_arguments(fmt0, orgap, if (__find_arguments(fmt0, orgap,
&argtable); &argtable) == -1) {
ret = -1;
goto done;
}
} }
goto rflag; goto rflag;
} }
@@ -594,7 +603,7 @@ reswitch: switch (ch) {
mbseqlen = wcrtomb(buf, mbseqlen = wcrtomb(buf,
(wchar_t)GETARG(wint_t), &mbs); (wchar_t)GETARG(wint_t), &mbs);
if (mbseqlen == (size_t)-1) { if (mbseqlen == (size_t)-1) {
errno = EILSEQ; ret = -1;
goto done; goto done;
} }
cp = buf; cp = buf;
@@ -795,44 +804,35 @@ fp_common:
xdigs = xdigs_lower; xdigs = xdigs_lower;
ox[1] = 'x'; ox[1] = 'x';
goto nosign; goto nosign;
case 's': case 's': {
size_t len;
#ifdef PRINTF_WIDE_CHAR #ifdef PRINTF_WIDE_CHAR
if (flags & LONGINT) { if (flags & LONGINT) {
wchar_t *wcp; wchar_t *wcp;
if (convbuf != NULL) { free(convbuf);
free(convbuf); convbuf = NULL;
convbuf = NULL;
}
if ((wcp = GETARG(wchar_t *)) == NULL) { if ((wcp = GETARG(wchar_t *)) == NULL) {
cp = (char *)"(null)"; cp = (char *)"(null)";
} else { } else {
convbuf = __wcsconv(wcp, prec); convbuf = __wcsconv(wcp, prec);
if (convbuf == NULL) if (convbuf == NULL) {
ret = -1;
goto done; goto done;
}
cp = convbuf; cp = convbuf;
} }
} else } else
#endif /* PRINTF_WIDE_CHAR */ #endif /* PRINTF_WIDE_CHAR */
if ((cp = GETARG(char *)) == NULL) if ((cp = GETARG(char *)) == NULL)
cp = (char *)"(null)"; cp = (char *)"(null)";
if (prec >= 0) { len = prec >= 0 ? strnlen(cp, prec) : strlen(cp);
/* if (len > INT_MAX)
* can't use strlen; can only look for the goto overflow;
* NUL in the first `prec' characters, and size = (int)len;
* strlen() will go further.
*/
char *p = memchr(cp, 0, prec);
size = p ? (p - cp) : prec;
} else {
size_t len;
if ((len = strlen(cp)) > INT_MAX)
goto overflow;
size = (int)len;
}
sign = '\0'; sign = '\0';
}
break; break;
case 'U': case 'U':
flags |= LONGINT; flags |= LONGINT;
@@ -1025,8 +1025,7 @@ overflow:
finish: finish:
#ifdef PRINTF_WIDE_CHAR #ifdef PRINTF_WIDE_CHAR
if (convbuf) free(convbuf);
free(convbuf);
#endif #endif
#ifdef FLOATING_POINT #ifdef FLOATING_POINT
if (dtoaresult) if (dtoaresult)
@@ -1085,7 +1084,7 @@ __find_arguments(const char *fmt0, va_list ap, union arg **argtable)
{ {
char *fmt; /* format string */ char *fmt; /* format string */
int ch; /* character from fmt */ int ch; /* character from fmt */
int n, n2; /* handy integer (short term usage) */ int n; /* handy integer (short term usage) */
char *cp; /* handy char pointer (short term usage) */ char *cp; /* handy char pointer (short term usage) */
int flags; /* flags as above */ int flags; /* flags as above */
unsigned char *typetable; /* table of types */ unsigned char *typetable; /* table of types */
@@ -1105,7 +1104,7 @@ __find_arguments(const char *fmt0, va_list ap, union arg **argtable)
typetable[nextarg++] = type) typetable[nextarg++] = type)
#define ADDSARG() \ #define ADDSARG() \
((flags&MAXINT) ? ADDTYPE(T_MAXINT) : \ ((flags&MAXINT) ? ADDTYPE(T_MAXINT) : \
((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \ ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
((flags&SIZEINT) ? ADDTYPE(T_SSIZEINT) : \ ((flags&SIZEINT) ? ADDTYPE(T_SSIZEINT) : \
((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \ ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \
@@ -1114,7 +1113,7 @@ __find_arguments(const char *fmt0, va_list ap, union arg **argtable)
((flags&CHARINT) ? ADDTYPE(T_CHAR) : ADDTYPE(T_INT)))))))) ((flags&CHARINT) ? ADDTYPE(T_CHAR) : ADDTYPE(T_INT))))))))
#define ADDUARG() \ #define ADDUARG() \
((flags&MAXINT) ? ADDTYPE(T_MAXUINT) : \ ((flags&MAXINT) ? ADDTYPE(T_MAXUINT) : \
((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \ ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
((flags&SIZEINT) ? ADDTYPE(T_SIZEINT) : \ ((flags&SIZEINT) ? ADDTYPE(T_SIZEINT) : \
((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \ ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \
@@ -1125,8 +1124,8 @@ __find_arguments(const char *fmt0, va_list ap, union arg **argtable)
/* /*
* Add * arguments to the type array. * Add * arguments to the type array.
*/ */
#define ADDASTER() \ #define ADDASTER() do { \
n2 = 0; \ int n2 = 0; \
cp = fmt; \ cp = fmt; \
while (is_digit(*cp)) { \ while (is_digit(*cp)) { \
APPEND_DIGIT(n2, *cp); \ APPEND_DIGIT(n2, *cp); \
@@ -1140,7 +1139,8 @@ __find_arguments(const char *fmt0, va_list ap, union arg **argtable)
fmt = ++cp; \ fmt = ++cp; \
} else { \ } else { \
ADDTYPE(T_INT); \ ADDTYPE(T_INT); \
} } \
} while (0)
fmt = (char *)fmt0; fmt = (char *)fmt0;
typetable = stattypetable; typetable = stattypetable;
tablesize = STATIC_ARG_TBL_SIZE; tablesize = STATIC_ARG_TBL_SIZE;
@@ -1153,8 +1153,8 @@ __find_arguments(const char *fmt0, va_list ap, union arg **argtable)
*/ */
for (;;) { for (;;) {
for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
/* void */; continue;
if ( ch == '\0' ) if (ch == '\0')
goto done; goto done;
fmt++; /* skip over '%' */ fmt++; /* skip over '%' */
@@ -1438,7 +1438,7 @@ __grow_type_table(unsigned char **typetable, int *tablesize)
unsigned char *new = sudo_mmap_alloc(newsize); unsigned char *new = sudo_mmap_alloc(newsize);
if (new == NULL) if (new == NULL)
return -1; return -1;
memmove(new, *typetable, *tablesize); memcpy(new, *typetable, *tablesize);
sudo_mmap_free(*typetable); sudo_mmap_free(*typetable);
*typetable = new; *typetable = new;
} }
@@ -1448,7 +1448,6 @@ __grow_type_table(unsigned char **typetable, int *tablesize)
return 0; return 0;
} }
#ifdef FLOATING_POINT #ifdef FLOATING_POINT
static int static int
exponent(char *p0, int exp, int fmtch) exponent(char *p0, int exp, int fmtch)