浏览代码

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.
Jelle Raaijmakers 3 年之前
父节点
当前提交
a44978b9b0
共有 2 个文件被更改,包括 4 次插入1 次删除
  1. 2 0
      Tests/LibC/TestScanf.cpp
  2. 2 1
      Userland/Libraries/LibC/scanf.cpp

+ 2 - 0
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;

+ 2 - 1
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;