diff --git a/lib/libc/locale/mbstowcs.c b/lib/libc/locale/mbstowcs.c index 5c60a5b2b04a..b473f89d33b7 100644 --- a/lib/libc/locale/mbstowcs.c +++ b/lib/libc/locale/mbstowcs.c @@ -37,6 +37,7 @@ #include __FBSDID("$FreeBSD$"); +#include #include #include #include @@ -50,18 +51,38 @@ mbstowcs(pwcs, s, n) { char const *e; int cnt = 0; + rune_t r; - if (!pwcs || !s) + if (!s) { + errno = EINVAL; return (-1); + } + if (pwcs == NULL) { + /* Convert and count only, do not store. */ + while ((r = sgetrune(s, MB_LEN_MAX, &e)) != _INVALID_RUNE && + r != 0) { + s = e; + cnt++; + } + if (r == _INVALID_RUNE) { + errno = EILSEQ; + return (-1); + } + } + + /* Convert, store and count characters. */ while (n-- > 0) { *pwcs = sgetrune(s, MB_LEN_MAX, &e); - if (*pwcs == _INVALID_RUNE) + if (*pwcs == _INVALID_RUNE) { + errno = EILSEQ; return (-1); + } if (*pwcs++ == 0) break; s = e; ++cnt; } + return (cnt); } diff --git a/lib/libc/locale/wcstombs.c b/lib/libc/locale/wcstombs.c index 987ec30296a3..ed9397ab90c1 100644 --- a/lib/libc/locale/wcstombs.c +++ b/lib/libc/locale/wcstombs.c @@ -37,6 +37,7 @@ #include __FBSDID("$FreeBSD$"); +#include #include #include #include @@ -48,26 +49,46 @@ wcstombs(s, pwcs, n) const wchar_t *pwcs; size_t n; { + char buf[MB_LEN_MAX]; char *e; int cnt, nb; - if (!pwcs || !s || n > INT_MAX) + if (!pwcs || n > INT_MAX) { + errno = EINVAL; return (-1); + } - nb = n; cnt = 0; + + if (s == NULL) { + /* Convert and count only, do not store. */ + while (*pwcs != L'\0') { + if (!sputrune(*pwcs++, buf, MB_LEN_MAX, &e)) { + errno = EILSEQ; + return (-1); + } + cnt += e - buf; + } + return (cnt); + } + + /* Convert, store and count characters. */ + nb = n; while (nb > 0) { if (*pwcs == 0) { *s = 0; break; } - if (!sputrune(*pwcs++, s, nb, &e)) - return (-1); /* encoding error */ + if (!sputrune(*pwcs++, s, nb, &e)) { + errno = EILSEQ; + return (-1); + } if (!e) /* too long */ return (cnt); cnt += e - s; nb -= e - s; s = e; } + return (cnt); }