diff --git a/libc/stdio/vcscanf.c b/libc/stdio/vcscanf.c index bf2b9ff36..f58f21e74 100644 --- a/libc/stdio/vcscanf.c +++ b/libc/stdio/vcscanf.c @@ -550,6 +550,11 @@ int __vcscanf(int callback(void *), // if (!j && c == -1 && !items) { items = -1; goto Done; + } else if (rawmode && j != width) { + /* The C standard says that %c "matches a sequence of characters of + * **exactly** the number specified by the field width". If we have + * fewer characters, what we've just read is invalid. */ + goto Done; } else if (!rawmode && j < bufsize) { if (charbytes == sizeof(char)) { buf[j] = '\0'; diff --git a/test/libc/stdio/sscanf_test.c b/test/libc/stdio/sscanf_test.c index 295706748..40e35f1c4 100644 --- a/test/libc/stdio/sscanf_test.c +++ b/test/libc/stdio/sscanf_test.c @@ -69,9 +69,17 @@ TEST(sscanf, testNonDirectiveCharacterMatching) { } TEST(sscanf, testCharacter) { - char c = 0; - EXPECT_EQ(1, sscanf("a", "%c", &c)); - EXPECT_EQ('a', c); + char c1 = 0, c2 = c1, c3 = c2, c4 = c3; + char s1[32] = {0}, s2[32] = {0}; + EXPECT_EQ(1, sscanf("a", "%c", &c1)); + EXPECT_EQ(2, sscanf("ab", "%c %c %c", &c2, &c3, &c4)); + EXPECT_EQ(1, sscanf("abcde", "%5c", s1)); + EXPECT_EQ(0, sscanf("abcd", "%5c", s2)); + + EXPECT_EQ('a', c1); + EXPECT_EQ('a', c2); + EXPECT_EQ('b', c3); + EXPECT_STREQ("abcde", &s1[0]); } TEST(sscanf, testStringBuffer) {