summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJelle Raaijmakers <jelle@gmta.nl>2021-10-25 00:23:49 +0200
committerBrian Gianforcaro <b.gianfo@gmail.com>2021-10-24 22:43:27 -0700
commita44978b9b005ed0b26774cae93816e90cbbd941d (patch)
treee710c381bf36c7954711e30bcf97c24571cee043
parent00f36fc5aedf15be19d1a458dabaa6714a21d8d8 (diff)
downloadserenity-a44978b9b005ed0b26774cae93816e90cbbd941d.zip
LibC: Fix `%n` conversion specifier in scanf() format
Also add a test to prevent this from happening again. There were two bugs: * The number of bytes just after processing the last value was written, instead of the number of bytes after skipping remaining whitespace. Confirmed by testing against GNU's `scanf()` since the man page leaves something to be desired. * The number of bytes was written to the wrong variable argument; i.e. the first argument was overwritten.
-rw-r--r--Tests/LibC/TestScanf.cpp2
-rw-r--r--Userland/Libraries/LibC/scanf.cpp3
2 files changed, 4 insertions, 1 deletions
diff --git a/Tests/LibC/TestScanf.cpp b/Tests/LibC/TestScanf.cpp
index 7993f4f1ec..dee99b6611 100644
--- a/Tests/LibC/TestScanf.cpp
+++ b/Tests/LibC/TestScanf.cpp
@@ -173,6 +173,8 @@ const TestSuite test_suites[] {
// Note: '9223372036854775806' is the max value for 'long long'.
{ "%lld", "9223372036854775805", 1, 1, { longlongarg0 }, { to_value_t(9223372036854775805LL) } },
{ "%llu", "9223372036854775810", 1, 1, { unsignedlonglongarg0 }, { to_value_t(9223372036854775810ULL) } },
+ { "%n", "", 0, 1, { intarg0 }, { to_value_t(0) } },
+ { "%d %n", "1 a", 1, 2, { intarg0, intarg1 }, { to_value_t(1), to_value_t(2) } },
};
bool g_any_failed = false;
diff --git a/Userland/Libraries/LibC/scanf.cpp b/Userland/Libraries/LibC/scanf.cpp
index ea88d572c2..d66043aa10 100644
--- a/Userland/Libraries/LibC/scanf.cpp
+++ b/Userland/Libraries/LibC/scanf.cpp
@@ -611,8 +611,9 @@ extern "C" int vsscanf(const char* input, const char* format, va_list ap)
++elements_matched;
break;
case ConversionSpecifier::OutputNumberOfBytes: {
+ input_lexer.ignore_while(isspace);
if (!suppress_assignment) {
- auto* ptr = va_arg(ap, int*);
+ auto* ptr = va_arg(copy, int*);
*ptr = input_lexer.tell();
}
break;