1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 07:18:11 +00:00

LibWeb: Make the CSS parser a little more tolerant to invalid CSS

Sometimes people put a '}' where it doesn't belong, or various other
things go wrong. 99% of the time, it's our fault, but either way,
this patch makes us not crash or infinite-loop in some common cases.

The real solution here is to write a proper CSS lexer-parser according
to the language spec, this is just a hack fix to make more sites load
at all.
This commit is contained in:
Andreas Kling 2020-05-26 22:29:37 +02:00
parent 72c52466e0
commit 7ed80ae96c

View file

@ -39,6 +39,11 @@
ASSERT_NOT_REACHED(); \ ASSERT_NOT_REACHED(); \
} }
#define PARSE_ERROR() \
do { \
dbg() << "CSS parse error"; \
} while (0)
namespace Web { namespace Web {
static CSS::ValueID value_id_for_palette_string(const StringView& string) static CSS::ValueID value_id_for_palette_string(const StringView& string)
@ -348,7 +353,9 @@ public:
if (peek() != ch) { if (peek() != ch) {
dbg() << "peek() != '" << ch << "'"; dbg() << "peek() != '" << ch << "'";
} }
PARSE_ASSERT(peek() == ch); if (peek() != ch) {
PARSE_ERROR();
}
PARSE_ASSERT(index < css.length()); PARSE_ASSERT(index < css.length());
++index; ++index;
return ch; return ch;
@ -512,7 +519,6 @@ public:
auto pseudo_name = String::copy(buffer); auto pseudo_name = String::copy(buffer);
buffer.clear(); buffer.clear();
// Ignore for now, otherwise we produce a "false positive" selector // Ignore for now, otherwise we produce a "false positive" selector
// and apply styles to the element itself, not its pseudo element // and apply styles to the element itself, not its pseudo element
if (is_pseudo_element) if (is_pseudo_element)
@ -590,12 +596,16 @@ public:
Vector<Selector::ComplexSelector> complex_selectors; Vector<Selector::ComplexSelector> complex_selectors;
for (;;) { for (;;) {
auto index_before = index;
auto complex_selector = parse_complex_selector(); auto complex_selector = parse_complex_selector();
if (complex_selector.has_value()) if (complex_selector.has_value())
complex_selectors.append(complex_selector.value()); complex_selectors.append(complex_selector.value());
consume_whitespace_or_comments(); consume_whitespace_or_comments();
if (!peek() || peek() == ',' || peek() == '{') if (!peek() || peek() == ',' || peek() == '{')
break; break;
// HACK: If we didn't move forward, just let go.
if (index == index_before)
break;
} }
if (complex_selectors.is_empty()) if (complex_selectors.is_empty())
@ -616,6 +626,7 @@ public:
void parse_selector_list() void parse_selector_list()
{ {
for (;;) { for (;;) {
auto index_before = index;
parse_selector(); parse_selector();
consume_whitespace_or_comments(); consume_whitespace_or_comments();
if (peek() == ',') { if (peek() == ',') {
@ -624,6 +635,9 @@ public:
} }
if (peek() == '{') if (peek() == '{')
break; break;
// HACK: If we didn't move forward, just let go.
if (index_before == index)
break;
} }
} }