5 changes: 4 additions & 1 deletion libc/src/stdio/scanf_core/scanf_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ int scanf_main(Reader *reader, const char *__restrict str,
cur_section = parser.get_next_section()) {
if (cur_section.has_conv) {
ret_val = convert(reader, cur_section);
conversions += ret_val == READ_OK ? 1 : 0;
// The %n (current position) conversion doesn't increment the number of
// assignments.
if (cur_section.conv_name != 'n')
conversions += ret_val == READ_OK ? 1 : 0;
} else {
ret_val = raw_match(reader, cur_section.raw_string);
}
Expand Down
67 changes: 62 additions & 5 deletions libc/test/src/stdio/sscanf_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,20 @@ TEST(LlvmLibcSScanfTest, IntConvSimple) {
EXPECT_EQ(ret_val, 1);
EXPECT_EQ(result, 345);

// 288 characters
ret_val = __llvm_libc::sscanf("10000000000000000000000000000000"
"00000000000000000000000000000000"
"00000000000000000000000000000000"
"00000000000000000000000000000000"
"00000000000000000000000000000000"
"00000000000000000000000000000000"
"00000000000000000000000000000000"
"00000000000000000000000000000000"
"00000000000000000000000000000000",
"%d", &result);
EXPECT_EQ(ret_val, 1);
EXPECT_EQ(result, int(__llvm_libc::cpp::numeric_limits<intmax_t>::max()));

ret_val = __llvm_libc::sscanf("Not an integer", "%d", &result);
EXPECT_EQ(ret_val, 0);
}
Expand Down Expand Up @@ -445,11 +459,6 @@ TEST(LlvmLibcSScanfTest, FloatConvComplexParsing) {
EXPECT_FP_EQ(result, 1.2);
}

/*
TODO:
Max width tests
*/

TEST(LlvmLibcSScanfTest, FloatConvMaxWidth) {
int ret_val;
float result = 0;
Expand Down Expand Up @@ -572,6 +581,54 @@ TEST(LlvmLibcSScanfTest, FloatConvNoWrite) {
EXPECT_EQ(ret_val, 0);
}

TEST(LlvmLibcSScanfTest, CurPosCombined) {
int ret_val;
int result = -1;
char c_result = 0;

ret_val = __llvm_libc::sscanf("some text", "%n", &result);
// %n doesn't count as a conversion for the return value.
EXPECT_EQ(ret_val, 0);
EXPECT_EQ(result, 0);

ret_val = __llvm_libc::sscanf("1234567890", "12345%n", &result);
EXPECT_EQ(ret_val, 0);
EXPECT_EQ(result, 5);

ret_val = __llvm_libc::sscanf("1234567890", "12345%n", &result);
EXPECT_EQ(ret_val, 0);
EXPECT_EQ(result, 5);

// 288 characters
ret_val = __llvm_libc::sscanf("10000000000000000000000000000000"
"00000000000000000000000000000000"
"00000000000000000000000000000000"
"00000000000000000000000000000000"
"00000000000000000000000000000000"
"00000000000000000000000000000000"
"00000000000000000000000000000000"
"00000000000000000000000000000000"
"00000000000000000000000000000000",
"%*d%hhn", &c_result);
EXPECT_EQ(ret_val, 1);
EXPECT_EQ(c_result, char(288)); // Overflow is handled by casting.

// 320 characters
ret_val = __llvm_libc::sscanf("10000000000000000000000000000000"
"00000000000000000000000000000000"
"00000000000000000000000000000000"
"00000000000000000000000000000000"
"00000000000000000000000000000000"
"00000000000000000000000000000000"
"00000000000000000000000000000000"
"00000000000000000000000000000000"
"00000000000000000000000000000000"
"00000000000000000000000000000000",
"%*d%n", &result);
EXPECT_EQ(ret_val, 1);
EXPECT_EQ(result, 320);
}

TEST(LlvmLibcSScanfTest, CombinedConv) {
int ret_val;
int result = 0;
Expand Down