diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-11-25 19:56:00 +0100 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-11-25 20:04:04 +0100 |
commit | 94bc46ee70a8f0c642297828dab8ab6502d03bd9 (patch) | |
tree | 6da7928593ba86217864ced41f8866de610f6a74 /Libraries/LibHTML | |
parent | 847b2326802de4f062d9f8910c34af20f53d873a (diff) | |
download | serenity-94bc46ee70a8f0c642297828dab8ab6502d03bd9.zip |
LibHTML: Improve CSS parser's handling of values somewhat
Now we just skip over url() and rgb() instead of crashing on them.
Diffstat (limited to 'Libraries/LibHTML')
-rw-r--r-- | Libraries/LibHTML/Parser/CSSParser.cpp | 92 |
1 files changed, 69 insertions, 23 deletions
diff --git a/Libraries/LibHTML/Parser/CSSParser.cpp b/Libraries/LibHTML/Parser/CSSParser.cpp index 4b25035c54..6bf0755bc5 100644 --- a/Libraries/LibHTML/Parser/CSSParser.cpp +++ b/Libraries/LibHTML/Parser/CSSParser.cpp @@ -374,6 +374,72 @@ public: return ch && ch != '!' && ch != ';' && ch != '}'; } + struct ValueAndImportant { + String value; + bool important { false }; + }; + + ValueAndImportant consume_css_value() + { + buffer.clear(); + + int paren_nesting_level = 0; + bool important = false; + + for (;;) { + char ch = peek(); + if (ch == '(') { + ++paren_nesting_level; + buffer.append(consume_one()); + continue; + } + if (ch == ')') { + PARSE_ASSERT(paren_nesting_level > 0); + --paren_nesting_level; + buffer.append(consume_one()); + continue; + } + if (paren_nesting_level > 0) { + buffer.append(consume_one()); + continue; + } + if (next_is("!important")) { + consume_specific('!'); + consume_specific('i'); + consume_specific('m'); + consume_specific('p'); + consume_specific('o'); + consume_specific('r'); + consume_specific('t'); + consume_specific('a'); + consume_specific('n'); + consume_specific('t'); + important = true; + continue; + } + if (next_is("/*")) { + consume_whitespace_or_comments(); + continue; + } + if (!ch) + break; + if (ch == '}') + break; + if (ch == ';') + break; + buffer.append(consume_one()); + } + + // Remove trailing whitespace. + while (!buffer.is_empty() && isspace(buffer.last())) + buffer.take_last(); + + auto string = String::copy(buffer); + buffer.clear(); + + return { string, important }; + } + Optional<StyleProperty> parse_property() { consume_whitespace_or_comments(); @@ -391,36 +457,16 @@ public: consume_whitespace_or_comments(); consume_specific(':'); consume_whitespace_or_comments(); - while (is_valid_property_value_char(peek())) - buffer.append(consume_one()); - // Remove trailing whitespace. - while (!buffer.is_empty() && isspace(buffer.last())) - buffer.take_last(); + auto [property_value, important] = consume_css_value(); - auto property_value = String::copy(buffer); - buffer.clear(); consume_whitespace_or_comments(); - bool is_important = false; - if (peek() == '!') { - consume_specific('!'); - consume_specific('i'); - consume_specific('m'); - consume_specific('p'); - consume_specific('o'); - consume_specific('r'); - consume_specific('t'); - consume_specific('a'); - consume_specific('n'); - consume_specific('t'); - consume_whitespace_or_comments(); - is_important = true; - } + if (peek() && peek() != '}') consume_specific(';'); auto property_id = CSS::property_id_from_string(property_name); - return StyleProperty { property_id, parse_css_value(property_value), is_important }; + return StyleProperty { property_id, parse_css_value(property_value), important }; } void parse_declaration() |