diff options
author | Jelle Raaijmakers <jelle@gmta.nl> | 2022-09-06 10:35:40 +0200 |
---|---|---|
committer | Sam Atkins <atkinssj@gmail.com> | 2022-09-09 22:54:25 +0100 |
commit | 325263f0e8f300b1b85b8061a54eba11f7df48c6 (patch) | |
tree | 5f0a537af11bae3245f67b45abd9d2ac87f5e20a | |
parent | 875ca2fb688ab2d1503020d7526163294fcbf8c2 (diff) | |
download | serenity-325263f0e8f300b1b85b8061a54eba11f7df48c6.zip |
LibC: Consume all whitespace in `scanf` if present in format
We were consuming all whitespace from the format, but not the input
lexer - that was left to the actual format parsing code. It so happened
that we did not account for whitespace with the conversion specifier
'[', causing whitespace to end up in the output variables.
Fix this by always consuming all whitespace and removing the whitespace
logic from the conversion code.
-rw-r--r-- | Tests/LibC/TestScanf.cpp | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibC/scanf.cpp | 25 |
2 files changed, 6 insertions, 20 deletions
diff --git a/Tests/LibC/TestScanf.cpp b/Tests/LibC/TestScanf.cpp index 5c1a1c934a..7e8623b16c 100644 --- a/Tests/LibC/TestScanf.cpp +++ b/Tests/LibC/TestScanf.cpp @@ -180,6 +180,7 @@ const TestSuite test_suites[] { { "%d %n", "1 a", 1, 2, { intarg0, intarg1 }, { to_value_t(1), to_value_t(2) } }, { "%*d", " 42", 0, 0, {}, {} }, { "%d%*1[:/]%d", "24/7", 2, 2, { intarg0, intarg1 }, { to_value_t(24), to_value_t(7) } }, + { " %[^a]", " b", 1, 1, { charstararg0 }, { str_to_value_t("b") } }, }; bool g_any_failed = false; diff --git a/Userland/Libraries/LibC/scanf.cpp b/Userland/Libraries/LibC/scanf.cpp index fa2e21fb30..2d4705ea58 100644 --- a/Userland/Libraries/LibC/scanf.cpp +++ b/Userland/Libraries/LibC/scanf.cpp @@ -62,8 +62,6 @@ template<typename ApT, ReadKind kind> struct ReadElementConcrete<int, ApT, kind> { bool operator()(GenericLexer& lexer, va_list* ap, bool suppress_assignment) { - lexer.ignore_while(isspace); - long value = 0; char* endptr = nullptr; auto nptr = lexer.remaining().characters_without_null_termination(); @@ -116,8 +114,6 @@ template<typename ApT, ReadKind kind> struct ReadElementConcrete<unsigned, ApT, kind> { bool operator()(GenericLexer& lexer, va_list* ap, bool suppress_assignment) { - lexer.ignore_while(isspace); - unsigned long value = 0; char* endptr = nullptr; auto nptr = lexer.remaining().characters_without_null_termination(); @@ -152,8 +148,6 @@ template<typename ApT, ReadKind kind> struct ReadElementConcrete<long long, ApT, kind> { bool operator()(GenericLexer& lexer, va_list* ap, bool suppress_assignment) { - lexer.ignore_while(isspace); - long long value = 0; char* endptr = nullptr; auto nptr = lexer.remaining().characters_without_null_termination(); @@ -188,8 +182,6 @@ template<typename ApT, ReadKind kind> struct ReadElementConcrete<unsigned long long, ApT, kind> { bool operator()(GenericLexer& lexer, va_list* ap, bool suppress_assignment) { - lexer.ignore_while(isspace); - unsigned long long value = 0; char* endptr = nullptr; auto nptr = lexer.remaining().characters_without_null_termination(); @@ -224,8 +216,6 @@ template<typename ApT, ReadKind kind> struct ReadElementConcrete<float, ApT, kind> { bool operator()(GenericLexer& lexer, va_list* ap, bool suppress_assignment) { - lexer.ignore_while(isspace); - double value = 0; char* endptr = nullptr; auto nptr = lexer.remaining().characters_without_null_termination(); @@ -299,7 +289,6 @@ struct ReadElement<char*, ReadKind::Normal> { ReadElement(StringView scan_set = {}, bool invert = false) : scan_set(scan_set.is_null() ? " \t\n\f\r"sv : scan_set) , invert(scan_set.is_null() ? true : invert) - , was_null(scan_set.is_null()) { } @@ -309,9 +298,6 @@ struct ReadElement<char*, ReadKind::Normal> { if (length_modifier != LengthModifier::Default) return false; - if (was_null) - input_lexer.ignore_while(isspace); - auto str = input_lexer.consume_while([this](auto c) { return this->matches(c); }); if (str.is_empty()) return false; @@ -333,7 +319,6 @@ private: const StringView scan_set; bool invert { false }; - bool was_null { false }; }; template<> @@ -343,8 +328,6 @@ struct ReadElement<void*, ReadKind::Normal> { if (length_modifier != LengthModifier::Default) return false; - input_lexer.ignore_while(isspace); - auto str = input_lexer.consume_while([this](auto c) { return this->should_consume(c); }); if (count != 8) { @@ -395,10 +378,13 @@ extern "C" int vsscanf(char const* input, char const* format, va_list ap) __builtin_va_copy(copy, ap); while (!format_lexer.is_eof()) { - format_lexer.ignore_while(isspace); + if (format_lexer.next_is(isspace)) { + format_lexer.ignore_while(isspace); + input_lexer.ignore_while(isspace); + } + if (!format_lexer.next_is('%')) { read_one_literal:; - input_lexer.ignore_while(isspace); if (format_lexer.is_eof()) break; @@ -619,7 +605,6 @@ extern "C" int vsscanf(char const* input, char const* format, va_list ap) ++elements_matched; break; case ConversionSpecifier::OutputNumberOfBytes: { - input_lexer.ignore_while(isspace); if (!suppress_assignment) { auto* ptr = va_arg(copy, int*); *ptr = input_lexer.tell(); |