Index: lib/libc/stdio/vsscanf.c =================================================================== --- lib/libc/stdio/vsscanf.c +++ lib/libc/stdio/vsscanf.c @@ -48,15 +48,40 @@ #include "local.h" #include "xlocale_private.h" -static int -eofread(void *, char *, int); +struct _sscancookie { + FILE *fp; + const char *str; +}; + +static int _vsscanf_read(void *, char *, int); + +#ifndef VSSCANF_CHUNK_SIZE +#define VSSCANF_CHUNK_SIZE 128 +#endif /* ARGSUSED */ static int -eofread(void *cookie, char *buf, int len) +_vsscanf_read(void *cookie, char *buf, int len) { + int n; + struct _sscancookie *sc; + + sc = (struct _sscancookie *)cookie; + + if (sc->str[0] == '\x00') + return (0); - return (0); + n = strnlen(sc->str, VSSCANF_CHUNK_SIZE); + + /* + * fp->_p is set in __srefill before calling us, this overwrites + * it so we don't have to copy the string into the buffer. + */ + sc->fp->_p = (unsigned char *)sc->str; + + sc->str += n; + + return n; } int @@ -64,12 +89,20 @@ const char * __restrict fmt, __va_list ap) { FILE f = FAKE_FILE; + struct _sscancookie sc; FIX_LOCALE(locale); f._flags = __SRD; f._bf._base = f._p = (unsigned char *)str; - f._bf._size = f._r = strlen(str); - f._read = eofread; + f._bf._size = f._r = strnlen(str, VSSCANF_CHUNK_SIZE); + f._read = _vsscanf_read; + + sc = (struct _sscancookie){ + .str = str + f._r, + .fp = &f, + }; + f._cookie = ≻ + return (__svfscanf(&f, locale, fmt, ap)); } int Index: lib/libc/string/strnlen.c =================================================================== --- lib/libc/string/strnlen.c +++ lib/libc/string/strnlen.c @@ -32,13 +32,14 @@ #include size_t -strnlen(const char *s, size_t maxlen) +strnlen(const char *ptr, size_t maxlen) { - size_t len; + const char *r; - for (len = 0; len < maxlen; len++, s++) { - if (!*s) - break; - } - return (len); + r = memchr(ptr, '\0', maxlen); + + if (r == NULL) + return maxlen; + + return r - ptr; }