summaryrefslogtreecommitdiff
path: root/Libraries/LibHTML
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-11-25 19:56:00 +0100
committerAndreas Kling <awesomekling@gmail.com>2019-11-25 20:04:04 +0100
commit94bc46ee70a8f0c642297828dab8ab6502d03bd9 (patch)
tree6da7928593ba86217864ced41f8866de610f6a74 /Libraries/LibHTML
parent847b2326802de4f062d9f8910c34af20f53d873a (diff)
downloadserenity-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.cpp92
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()