Sync with OpenBSD.
This commit is contained in:
@@ -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)
|
||||||
|
Reference in New Issue
Block a user