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.
This commit is contained in:
Jelle Raaijmakers 2021-10-25 00:23:49 +02:00 committed by Brian Gianforcaro
parent 00f36fc5ae
commit a44978b9b0
Notes: sideshowbarker 2024-07-18 01:54:50 +09:00
2 changed files with 4 additions and 1 deletions

View file

@ -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;

View file

@ -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;