summaryrefslogtreecommitdiff
path: root/lib/libc
diff options
context:
space:
mode:
authorTheo Buehler <tb@cvs.openbsd.org>2017-11-21 17:48:20 +0000
committerTheo Buehler <tb@cvs.openbsd.org>2017-11-21 17:48:20 +0000
commitbaaf0fc648825517c0585240c17d975e07d1dca3 (patch)
treed20b05626af495547260a4a9be3df71ffcda3529 /lib/libc
parent23aaf32da78cb518b4890539ef07217df98d0c58 (diff)
Use a simple forward search to find '%' in the format string instead of
using mbrtowc(3). Thus, we now treat the format string as a bytestring, not as a multibyte character string. We think that ANSI C made a small error when adding wide characters: The committees essentially replaced "characters" with "wide characters" in the existing printf documentation, which was written before the concept of processing was established. Doing processing on the format string would break some 8-bit format strings in the wild, and that isn't something these committees gave themselves license to do. Based on the "10x printf speedup" commit from android found by tedu: https://github.com/aosp-mirror/platform_bionic/commit/5305a4d4a723b06494b93f2df81733b83a0c46d3 Thanks to millert and schwarze for digging into the history and testing *printf behavior on other platforms. ok deraadt, millert
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/stdio/vfprintf.c47
1 files changed, 12 insertions, 35 deletions
diff --git a/lib/libc/stdio/vfprintf.c b/lib/libc/stdio/vfprintf.c
index 7d8ccea9e3c..1d451a84f66 100644
--- a/lib/libc/stdio/vfprintf.c
+++ b/lib/libc/stdio/vfprintf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfprintf.c,v 1.77 2016/08/29 12:20:57 millert Exp $ */
+/* $OpenBSD: vfprintf.c,v 1.78 2017/11/21 17:48:19 tb Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
@@ -279,8 +279,6 @@ __vfprintf(FILE *fp, const char *fmt0, __va_list ap)
int width; /* width from format (%8d), or 0 */
int prec; /* precision from format; <0 for N/A */
char sign; /* sign prefix (' ', '+', '-', or \0) */
- wchar_t wc;
- mbstate_t ps;
#ifdef FLOATING_POINT
/*
* We can decompose the printed representation of floating
@@ -481,25 +479,13 @@ __vfprintf(FILE *fp, const char *fmt0, __va_list ap)
convbuf = NULL;
#endif
- memset(&ps, 0, sizeof(ps));
/*
* Scan the format for conversions (`%' character).
*/
for (;;) {
- size_t len;
+ for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
+ continue;
- cp = fmt;
- while ((len = mbrtowc(&wc, fmt, MB_CUR_MAX, &ps)) != 0) {
- if (len == (size_t)-1 || len == (size_t)-2) {
- ret = -1;
- goto error;
- }
- fmt += len;
- if (wc == '%') {
- fmt--;
- break;
- }
- }
if (fmt != cp) {
ptrdiff_t m = fmt - cp;
if (m < 0 || m > INT_MAX - ret)
@@ -507,7 +493,7 @@ __vfprintf(FILE *fp, const char *fmt0, __va_list ap)
PRINT(cp, m);
ret += m;
}
- if (len == 0)
+ if (ch == '\0')
goto done;
fmt++; /* skip over '%' */
@@ -852,7 +838,9 @@ fp_common:
xdigs = xdigs_lower;
ox[1] = 'x';
goto nosign;
- case 's':
+ case 's': {
+ size_t len;
+
#ifdef PRINTF_WIDE_CHAR
if (flags & LONGINT) {
wchar_t *wcp;
@@ -878,6 +866,7 @@ fp_common:
}
} else
#endif /* PRINTF_WIDE_CHAR */
+
if ((cp = GETARG(char *)) == NULL) {
struct syslog_data sdata = SYSLOG_DATA_INIT;
int save_errno = errno;
@@ -893,6 +882,7 @@ fp_common:
goto overflow;
size = (int)len;
sign = '\0';
+ }
break;
case 'U':
flags |= LONGINT;
@@ -1156,8 +1146,6 @@ __find_arguments(const char *fmt0, va_list ap, union arg **argtable,
int tablemax; /* largest used index in table */
int nextarg; /* 1-based argument index */
int ret = 0; /* return value */
- wchar_t wc;
- mbstate_t ps;
/*
* Add an argument type to the table, expanding if necessary.
@@ -1211,25 +1199,14 @@ __find_arguments(const char *fmt0, va_list ap, union arg **argtable,
tablemax = 0;
nextarg = 1;
memset(typetable, T_UNUSED, STATIC_ARG_TBL_SIZE);
- memset(&ps, 0, sizeof(ps));
/*
* Scan the format for conversions (`%' character).
*/
for (;;) {
- size_t len;
-
- cp = fmt;
- while ((len = mbrtowc(&wc, fmt, MB_CUR_MAX, &ps)) != 0) {
- if (len == (size_t)-1 || len == (size_t)-2)
- return (-1);
- fmt += len;
- if (wc == '%') {
- fmt--;
- break;
- }
- }
- if (len == 0)
+ for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
+ continue;
+ if (ch == '\0')
goto done;
fmt++; /* skip over '%' */