diff --git a/Userland/Libraries/LibC/scanf.cpp b/Userland/Libraries/LibC/scanf.cpp index f7d676ad9b..0c61c4fdc5 100644 --- a/Userland/Libraries/LibC/scanf.cpp +++ b/Userland/Libraries/LibC/scanf.cpp @@ -84,7 +84,7 @@ struct ReadElementConcrete { { lexer.ignore_while(isspace); - auto* ptr = va_arg(*ap, ApT*); + auto* ptr = ap ? va_arg(*ap, ApT*) : nullptr; long value = 0; char* endptr = nullptr; auto nptr = lexer.remaining().characters_without_null_termination(); @@ -107,7 +107,8 @@ struct ReadElementConcrete { VERIFY(diff > 0); lexer.ignore((size_t)diff); - *ptr = value; + if (ptr) + *ptr = value; return true; } }; @@ -118,13 +119,14 @@ struct ReadElementConcrete { { static_assert(kind == ReadKind::Normal, "Can't read a non-normal character"); - auto* ptr = va_arg(*ap, ApT*); + auto* ptr = ap ? va_arg(*ap, ApT*) : nullptr; if (lexer.is_eof()) return false; auto ch = lexer.consume(); - *ptr = ch; + if (ptr) + *ptr = ch; return true; } }; @@ -135,7 +137,7 @@ struct ReadElementConcrete { { lexer.ignore_while(isspace); - auto* ptr = va_arg(*ap, ApT*); + auto* ptr = ap ? va_arg(*ap, ApT*) : nullptr; unsigned long value = 0; char* endptr = nullptr; auto nptr = lexer.remaining().characters_without_null_termination(); @@ -158,7 +160,8 @@ struct ReadElementConcrete { VERIFY(diff > 0); lexer.ignore((size_t)diff); - *ptr = value; + if (ptr) + *ptr = value; return true; } }; @@ -169,7 +172,7 @@ struct ReadElementConcrete { { lexer.ignore_while(isspace); - auto* ptr = va_arg(*ap, ApT*); + auto* ptr = ap ? va_arg(*ap, ApT*) : nullptr; long long value = 0; char* endptr = nullptr; auto nptr = lexer.remaining().characters_without_null_termination(); @@ -192,7 +195,8 @@ struct ReadElementConcrete { VERIFY(diff > 0); lexer.ignore((size_t)diff); - *ptr = value; + if (ptr) + *ptr = value; return true; } }; @@ -203,7 +207,7 @@ struct ReadElementConcrete { { lexer.ignore_while(isspace); - auto* ptr = va_arg(*ap, ApT*); + auto* ptr = ap ? va_arg(*ap, ApT*) : nullptr; unsigned long long value = 0; char* endptr = nullptr; auto nptr = lexer.remaining().characters_without_null_termination(); @@ -226,7 +230,8 @@ struct ReadElementConcrete { VERIFY(diff > 0); lexer.ignore((size_t)diff); - *ptr = value; + if (ptr) + *ptr = value; return true; } }; @@ -237,7 +242,7 @@ struct ReadElementConcrete { { lexer.ignore_while(isspace); - auto* ptr = va_arg(*ap, ApT*); + auto* ptr = ap ? va_arg(*ap, ApT*) : nullptr; double value = 0; char* endptr = nullptr; @@ -257,7 +262,8 @@ struct ReadElementConcrete { VERIFY(diff > 0); lexer.ignore((size_t)diff); - *ptr = value; + if (ptr) + *ptr = value; return true; } }; @@ -322,7 +328,7 @@ struct ReadElement { if (was_null) input_lexer.ignore_while(isspace); - auto* ptr = va_arg(*ap, char*); + auto* ptr = ap ? va_arg(*ap, char*) : nullptr; auto str = input_lexer.consume_while([this](auto c) { return this->matches(c); }); if (str.is_empty()) return false; @@ -353,7 +359,7 @@ struct ReadElement { input_lexer.ignore_while(isspace); - auto* ptr = va_arg(*ap, void**); + auto* ptr = ap ? va_arg(*ap, void**) : nullptr; auto str = input_lexer.consume_while([this](auto c) { return this->should_consume(c); }); if (count != 8) { @@ -418,6 +424,12 @@ extern "C" int vsscanf(const char* input, const char* format, va_list ap) format_lexer.ignore(); // '%' + bool suppress_assignment = false; + if (format_lexer.next_is('*')) { + suppress_assignment = true; + format_lexer.ignore(); + } + // Parse width specification [[maybe_unused]] int width_specifier = 0; if (format_lexer.next_is(isdigit)) { @@ -545,6 +557,8 @@ extern "C" int vsscanf(const char* input, const char* format, va_list ap) } } + auto* ap_or_null = !suppress_assignment ? (va_list*)&ap : nullptr; + // Now try to read. switch (conversion_specifier) { case Invalid: @@ -554,68 +568,70 @@ extern "C" int vsscanf(const char* input, const char* format, va_list ap) dbgln("Invalid conversion specifier {} in scanf!", (int)conversion_specifier); VERIFY_NOT_REACHED(); case Decimal: - if (!ReadElement {}(length_modifier, input_lexer, (va_list*)&ap)) + if (!ReadElement {}(length_modifier, input_lexer, ap_or_null)) format_lexer.consume_all(); else ++elements_matched; break; case Integer: - if (!ReadElement {}(length_modifier, input_lexer, (va_list*)&ap)) + if (!ReadElement {}(length_modifier, input_lexer, ap_or_null)) format_lexer.consume_all(); else ++elements_matched; break; case Octal: - if (!ReadElement {}(length_modifier, input_lexer, (va_list*)&ap)) + if (!ReadElement {}(length_modifier, input_lexer, ap_or_null)) format_lexer.consume_all(); else ++elements_matched; break; case Unsigned: - if (!ReadElement {}(length_modifier, input_lexer, (va_list*)&ap)) + if (!ReadElement {}(length_modifier, input_lexer, ap_or_null)) format_lexer.consume_all(); else ++elements_matched; break; case Hex: - if (!ReadElement {}(length_modifier, input_lexer, (va_list*)&ap)) + if (!ReadElement {}(length_modifier, input_lexer, ap_or_null)) format_lexer.consume_all(); else ++elements_matched; break; case Floating: - if (!ReadElement {}(length_modifier, input_lexer, (va_list*)&ap)) + if (!ReadElement {}(length_modifier, input_lexer, ap_or_null)) format_lexer.consume_all(); else ++elements_matched; break; case String: - if (!ReadElement {}(length_modifier, input_lexer, (va_list*)&ap)) + if (!ReadElement {}(length_modifier, input_lexer, ap_or_null)) format_lexer.consume_all(); else ++elements_matched; break; case UseScanList: - if (!ReadElement { scanlist, invert_scanlist }(length_modifier, input_lexer, (va_list*)&ap)) + if (!ReadElement { scanlist, invert_scanlist }(length_modifier, input_lexer, ap_or_null)) format_lexer.consume_all(); else ++elements_matched; break; case Character: - if (!ReadElement {}(length_modifier, input_lexer, (va_list*)&ap)) + if (!ReadElement {}(length_modifier, input_lexer, ap_or_null)) format_lexer.consume_all(); else ++elements_matched; break; case Pointer: - if (!ReadElement {}(length_modifier, input_lexer, (va_list*)&ap)) + if (!ReadElement {}(length_modifier, input_lexer, ap_or_null)) format_lexer.consume_all(); else ++elements_matched; break; case OutputNumberOfBytes: { - auto* ptr = va_arg(ap, int*); - *ptr = input_lexer.tell(); + if (!suppress_assignment) { + auto* ptr = va_arg(ap, int*); + *ptr = input_lexer.tell(); + } ++elements_matched; break; }