summaryrefslogtreecommitdiffstats
path: root/lib/libc/stdio
diff options
context:
space:
mode:
authordas <das@FreeBSD.org>2012-04-30 01:08:18 +0000
committerdas <das@FreeBSD.org>2012-04-30 01:08:18 +0000
commitc518692b2d5df8a7142f20783c37cea469c0b20b (patch)
tree09ba731f19402af09350cecd89001b1f297cb59b /lib/libc/stdio
parent5fb190b2b7edf0bf9cabd4a770e52a9d17b292ba (diff)
downloadFreeBSD-src-c518692b2d5df8a7142f20783c37cea469c0b20b.zip
FreeBSD-src-c518692b2d5df8a7142f20783c37cea469c0b20b.tar.gz
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.
Diffstat (limited to 'lib/libc/stdio')
-rw-r--r--lib/libc/stdio/vfwscanf.c53
1 files changed, 9 insertions, 44 deletions
diff --git a/lib/libc/stdio/vfwscanf.c b/lib/libc/stdio/vfwscanf.c
index 6b4d8c5..c542084 100644
--- a/lib/libc/stdio/vfwscanf.c
+++ b/lib/libc/stdio/vfwscanf.c
@@ -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)
OpenPOWER on IntegriCloud