Fix a bug in *wscanf's handling of non-wide %s, %c, and %[

conversions.  Both the specification and the documentation say the
width is interpreted as the max number of wide characters to read, but
the implementation was interpreting it as the number of bytes to convert.
(See also r105317.)

This change has security implications for any applications that depend
on the buggy behavior, but the impact in practice is probably nil.
Any such application would already be buggy on other platforms that
get the semantics right.  Also, these conversions are rarely used;
%ls, %lc, and %l[ are more appropriate.
This commit is contained in:
das 2012-04-30 01:08:18 +00:00
parent 5fb190b2b7
commit c518692b2d

View File

@ -144,29 +144,16 @@ convert_char(FILE *fp, char * __restrict mbp, int width, locale_t locale)
size_t nconv;
wint_t wi;
int n;
char mbbuf[MB_LEN_MAX];
n = 0;
mbs = initial_mbs;
while (width != 0 && (wi = __fgetwc(fp, locale)) != WEOF) {
if (width >= MB_CUR_MAX && mbp != SUPPRESS_PTR) {
while (width-- != 0 && (wi = __fgetwc(fp, locale)) != WEOF) {
if (mbp != SUPPRESS_PTR) {
nconv = wcrtomb(mbp, wi, &mbs);
if (nconv == (size_t)-1)
return (-1);
} else {
nconv = wcrtomb(mbbuf, wi, &mbs);
if (nconv == (size_t)-1)
return (-1);
if (nconv > width) {
__ungetwc(wi, fp, locale);
break;
}
if (mbp != SUPPRESS_PTR)
memcpy(mbp, mbbuf, nconv);
}
if (mbp != SUPPRESS_PTR)
mbp += nconv;
width -= nconv;
}
n++;
}
if (n == 0)
@ -199,28 +186,17 @@ convert_ccl(FILE *fp, char * __restrict mbp, int width, const struct ccl *ccl,
size_t nconv;
wint_t wi;
int n;
char mbbuf[MB_LEN_MAX];
n = 0;
mbs = initial_mbs;
while ((wi = __fgetwc(fp, locale)) != WEOF &&
width != 0 && inccl(ccl, wi)) {
if (width >= MB_CUR_MAX && mbp != SUPPRESS_PTR) {
width-- != 0 && inccl(ccl, wi)) {
if (mbp != SUPPRESS_PTR) {
nconv = wcrtomb(mbp, wi, &mbs);
if (nconv == (size_t)-1)
return (-1);
} else {
nconv = wcrtomb(mbbuf, wi, &mbs);
if (nconv == (size_t)-1)
return (-1);
if (nconv > width)
break;
if (mbp != SUPPRESS_PTR)
memcpy(mbp, mbbuf, nconv);
}
if (mbp != SUPPRESS_PTR)
mbp += nconv;
width -= nconv;
}
n++;
}
if (wi != WEOF)
@ -267,28 +243,17 @@ convert_string(FILE *fp, char * __restrict mbp, int width, locale_t locale)
size_t nconv;
wint_t wi;
int nread;
char mbbuf[MB_LEN_MAX];
mbs = initial_mbs;
nread = 0;
while ((wi = __fgetwc(fp, locale)) != WEOF && width != 0 &&
while ((wi = __fgetwc(fp, locale)) != WEOF && width-- != 0 &&
!iswspace(wi)) {
if (width >= MB_CUR_MAX && mbp != SUPPRESS_PTR) {
if (mbp != SUPPRESS_PTR) {
nconv = wcrtomb(mbp, wi, &mbs);
if (nconv == (size_t)-1)
return (-1);
} else {
nconv = wcrtomb(mbbuf, wi, &mbs);
if (nconv == (size_t)-1)
return (-1);
if (nconv > width)
break;
if (mbp != SUPPRESS_PTR)
memcpy(mbp, mbbuf, nconv);
}
if (mbp != SUPPRESS_PTR)
mbp += nconv;
width -= nconv;
}
nread++;
}
if (wi != WEOF)