diff options
author | Sam Atkins <atkinssj@gmail.com> | 2021-07-07 20:47:09 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-07-11 23:19:56 +0200 |
commit | e5ac5e1fabfa5c6f413b363ae9abef0302cbacd9 (patch) | |
tree | dcdf9f21d06b3c07c7ab4111887e5c4925c95179 /Userland/Libraries | |
parent | 78d191554a23ea5e923abc2659581d090ece8430 (diff) | |
download | serenity-e5ac5e1fabfa5c6f413b363ae9abef0302cbacd9.zip |
LibWeb: Fix CSS attribute and ID selector parsing
There were several crashes here from out-of-bounds memory access.
Diffstat (limited to 'Userland/Libraries')
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp | 34 |
1 files changed, 20 insertions, 14 deletions
diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index 2603e75b10..8c22d9936e 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -231,7 +231,6 @@ Optional<Selector> Parser::parse_single_selector(TokenStream<T>& tokens, bool is auto parse_simple_selector = [&]() -> Optional<Selector::SimpleSelector> { auto current_value = tokens.next_token(); - dbgln("parse_simple_selector, start token: {}", current_value.to_string()); if (check_for_eof_or_whitespace(current_value)) return {}; @@ -267,11 +266,19 @@ Optional<Selector> Parser::parse_single_selector(TokenStream<T>& tokens, bool is type = Selector::SimpleSelector::Type::Class; value = current_value.to_string(); - } else if (current_value.is(Token::Type::Delim) && ((Token)current_value).delim() == "*") { + } else if (current_value.is(Token::Type::Delim) && current_value.token().delim() == "*") { type = Selector::SimpleSelector::Type::Universal; - } else { + } else if (current_value.is(Token::Type::Ident)) { type = Selector::SimpleSelector::Type::TagName; - value = current_value.to_string().to_lowercase(); + value = current_value.token().ident().to_lowercase_string(); + } else if ((current_value.is(Token::Type::Delim) && current_value.token().delim() == ":") + || (current_value.is_block() && current_value.block().is_square())) { + // FIXME: This is a temporary hack until we make the Selector::SimpleSelector::Type changes. + type = Selector::SimpleSelector::Type::Universal; + tokens.reconsume_current_input_token(); + } else { + dbgln("Invalid simple selector!"); + return {}; } Selector::SimpleSelector simple_selector; @@ -302,13 +309,10 @@ Optional<Selector> Parser::parse_single_selector(TokenStream<T>& tokens, bool is simple_selector.attribute_match_type = Selector::SimpleSelector::AttributeMatchType::HasAttribute; simple_selector.attribute_name = attribute_part.token().ident(); - size_t attribute_index = 0; - while (attribute_parts.at(attribute_index).is(Token::Type::Whitespace)) { - attribute_index++; - if (attribute_index >= attribute_parts.size()) - return simple_selector; - } + if (attribute_parts.size() == 1) + return simple_selector; + size_t attribute_index = 1; auto& delim_part = attribute_parts.at(attribute_index); if (!delim_part.is(Token::Type::Delim)) { dbgln("Expected a delim for attribute comparison, got: '{}'", delim_part.to_string()); @@ -326,7 +330,7 @@ Optional<Selector> Parser::parse_single_selector(TokenStream<T>& tokens, bool is } auto& delim_second_part = attribute_parts.at(attribute_index); - if (!(delim_part.is(Token::Type::Delim) && delim_part.token().delim() == "=")) { + if (!(delim_second_part.is(Token::Type::Delim) && delim_second_part.token().delim() == "=")) { dbgln("Expected a double delim for attribute comparison, got: '{}{}'", delim_part.to_string(), delim_second_part.to_string()); return {}; } @@ -450,6 +454,8 @@ Optional<Selector> Parser::parse_single_selector(TokenStream<T>& tokens, bool is } } + tokens.reconsume_current_input_token(); + return simple_selector; }; @@ -785,12 +791,12 @@ Optional<StyleDeclarationRule> Parser::consume_a_declaration(TokenStream<T>& tok } } - for (;;) { - auto maybe_whitespace = declaration.m_values.at(declaration.m_values.size() - 1); + while (!declaration.m_values.is_empty()) { + auto maybe_whitespace = declaration.m_values.last(); if (!(maybe_whitespace.is(Token::Type::Whitespace))) { break; } - declaration.m_values.remove(declaration.m_values.size() - 1); + declaration.m_values.take_last(); } return declaration; |