diff options
author | Jelle Raaijmakers <jelle@gmta.nl> | 2021-10-25 00:23:49 +0200 |
---|---|---|
committer | Brian Gianforcaro <b.gianfo@gmail.com> | 2021-10-24 22:43:27 -0700 |
commit | a44978b9b005ed0b26774cae93816e90cbbd941d (patch) | |
tree | e710c381bf36c7954711e30bcf97c24571cee043 | |
parent | 00f36fc5aedf15be19d1a458dabaa6714a21d8d8 (diff) | |
download | serenity-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.cpp | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibC/scanf.cpp | 3 |
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; |