LibWeb: Reject invalid alt text values in CSS content property parsing

The CSS content property's alt text (after `/`) was incorrectly
accepting any content value. Per the CSS Content Module Level 3 spec,
alt text only accepts <string>, <counter>, and <attr()> values. This
change adds type validation in the alt text parsing branch to reject
URLs, quote keywords, images, and other non-alt-text value types.

This fixes 64 subtests in the content-invalid WPT test.
This commit is contained in:
Adam Colvin 2026-02-21 12:09:10 +00:00 committed by Tim Flynn
parent 55f4009163
commit d2f10c76fd
2 changed files with 71 additions and 66 deletions

View file

@ -2242,6 +2242,11 @@ RefPtr<StyleValue const> Parser::parse_content_value(TokenStream<ComponentValue>
return nullptr;
if (in_alt_text) {
// https://drafts.csswg.org/css-content-3/#content-property
// / [ <string> | <counter> | <attr()> ]+
// NB: <attr()> is handled as an arbitrary substitution function and does not reach this code path.
if (!style_value->is_string() && !style_value->is_counter())
return nullptr;
alt_text_values.append(style_value.release_nonnull());
} else {
content_values.append(style_value.release_nonnull());

View file

@ -2,75 +2,75 @@ Harness status: OK
Found 70 tests
4 Pass
66 Fail
68 Pass
2 Fail
Fail e.style['content'] = "attr()" should not set the property value
Fail e.style['content'] = "attr() / \"alt text\"" should not set the property value
Pass e.style['content'] = "counters(counter-name)" should not set the property value
Pass e.style['content'] = "counters(counter-name) / \"alt text\"" should not set the property value
Pass e.style['content'] = "counter()" should not set the property value
Pass e.style['content'] = "counter() / \"alt text\"" should not set the property value
Fail e.style['content'] = "open-quote / url(\"https://www.example.com/picture.svg\")" should not set the property value
Fail e.style['content'] = "open-quote / no-open-quote" should not set the property value
Fail e.style['content'] = "open-quote / no-close-quote" should not set the property value
Fail e.style['content'] = "open-quote / \"hi\" no-close-quote" should not set the property value
Fail e.style['content'] = "close-quote / url(\"https://www.example.com/picture.svg\")" should not set the property value
Fail e.style['content'] = "close-quote / no-open-quote" should not set the property value
Fail e.style['content'] = "close-quote / no-close-quote" should not set the property value
Fail e.style['content'] = "close-quote / \"hi\" no-close-quote" should not set the property value
Fail e.style['content'] = "no-open-quote / url(\"https://www.example.com/picture.svg\")" should not set the property value
Fail e.style['content'] = "no-open-quote / no-open-quote" should not set the property value
Fail e.style['content'] = "no-open-quote / no-close-quote" should not set the property value
Fail e.style['content'] = "no-open-quote / \"hi\" no-close-quote" should not set the property value
Fail e.style['content'] = "no-close-quote / url(\"https://www.example.com/picture.svg\")" should not set the property value
Fail e.style['content'] = "no-close-quote / no-open-quote" should not set the property value
Fail e.style['content'] = "no-close-quote / no-close-quote" should not set the property value
Fail e.style['content'] = "no-close-quote / \"hi\" no-close-quote" should not set the property value
Fail e.style['content'] = "counter(counter-name) / url(\"https://www.example.com/picture.svg\")" should not set the property value
Fail e.style['content'] = "counter(counter-name) / no-open-quote" should not set the property value
Fail e.style['content'] = "counter(counter-name) / no-close-quote" should not set the property value
Fail e.style['content'] = "counter(counter-name) / \"hi\" no-close-quote" should not set the property value
Fail e.style['content'] = "counter(counter-name, counter-style) / url(\"https://www.example.com/picture.svg\")" should not set the property value
Fail e.style['content'] = "counter(counter-name, counter-style) / no-open-quote" should not set the property value
Fail e.style['content'] = "counter(counter-name, counter-style) / no-close-quote" should not set the property value
Fail e.style['content'] = "counter(counter-name, counter-style) / \"hi\" no-close-quote" should not set the property value
Fail e.style['content'] = "counters(counter-name, \".\") / url(\"https://www.example.com/picture.svg\")" should not set the property value
Fail e.style['content'] = "counters(counter-name, \".\") / no-open-quote" should not set the property value
Fail e.style['content'] = "counters(counter-name, \".\") / no-close-quote" should not set the property value
Fail e.style['content'] = "counters(counter-name, \".\") / \"hi\" no-close-quote" should not set the property value
Fail e.style['content'] = "counters(counter-name, \".\", counter-style) / url(\"https://www.example.com/picture.svg\")" should not set the property value
Fail e.style['content'] = "counters(counter-name, \".\", counter-style) / no-open-quote" should not set the property value
Fail e.style['content'] = "counters(counter-name, \".\", counter-style) / no-close-quote" should not set the property value
Fail e.style['content'] = "counters(counter-name, \".\", counter-style) / \"hi\" no-close-quote" should not set the property value
Fail e.style['content'] = "url(\"https://www.example.com/picture.svg\") / url(\"https://www.example.com/picture.svg\")" should not set the property value
Fail e.style['content'] = "url(\"https://www.example.com/picture.svg\") / no-open-quote" should not set the property value
Fail e.style['content'] = "url(\"https://www.example.com/picture.svg\") / no-close-quote" should not set the property value
Fail e.style['content'] = "url(\"https://www.example.com/picture.svg\") / \"hi\" no-close-quote" should not set the property value
Fail e.style['content'] = "\"hello\" / url(\"https://www.example.com/picture.svg\")" should not set the property value
Fail e.style['content'] = "\"hello\" / no-open-quote" should not set the property value
Fail e.style['content'] = "\"hello\" / no-close-quote" should not set the property value
Fail e.style['content'] = "\"hello\" / \"hi\" no-close-quote" should not set the property value
Fail e.style['content'] = "\"hello\" \"world\" / url(\"https://www.example.com/picture.svg\")" should not set the property value
Fail e.style['content'] = "\"hello\" \"world\" / no-open-quote" should not set the property value
Fail e.style['content'] = "\"hello\" \"world\" / no-close-quote" should not set the property value
Fail e.style['content'] = "\"hello\" \"world\" / \"hi\" no-close-quote" should not set the property value
Fail e.style['content'] = "counter(counter-name) \"potato\" / url(\"https://www.example.com/picture.svg\")" should not set the property value
Fail e.style['content'] = "counter(counter-name) \"potato\" / no-open-quote" should not set the property value
Fail e.style['content'] = "counter(counter-name) \"potato\" / no-close-quote" should not set the property value
Fail e.style['content'] = "counter(counter-name) \"potato\" / \"hi\" no-close-quote" should not set the property value
Fail e.style['content'] = "counters(counter-name, \".\") \"potato\" / url(\"https://www.example.com/picture.svg\")" should not set the property value
Fail e.style['content'] = "counters(counter-name, \".\") \"potato\" / no-open-quote" should not set the property value
Fail e.style['content'] = "counters(counter-name, \".\") \"potato\" / no-close-quote" should not set the property value
Fail e.style['content'] = "counters(counter-name, \".\") \"potato\" / \"hi\" no-close-quote" should not set the property value
Fail e.style['content'] = "\"(\" counters(counter-name, \".\", counter-style) \")\" / url(\"https://www.example.com/picture.svg\")" should not set the property value
Fail e.style['content'] = "\"(\" counters(counter-name, \".\", counter-style) \")\" / no-open-quote" should not set the property value
Fail e.style['content'] = "\"(\" counters(counter-name, \".\", counter-style) \")\" / no-close-quote" should not set the property value
Fail e.style['content'] = "\"(\" counters(counter-name, \".\", counter-style) \")\" / \"hi\" no-close-quote" should not set the property value
Fail e.style['content'] = "open-quote \"hello\" \"world\" close-quote / url(\"https://www.example.com/picture.svg\")" should not set the property value
Fail e.style['content'] = "open-quote \"hello\" \"world\" close-quote / no-open-quote" should not set the property value
Fail e.style['content'] = "open-quote \"hello\" \"world\" close-quote / no-close-quote" should not set the property value
Fail e.style['content'] = "open-quote \"hello\" \"world\" close-quote / \"hi\" no-close-quote" should not set the property value
Fail e.style['content'] = "url(\"https://www.example.com/picture.svg\") \"hello\" / url(\"https://www.example.com/picture.svg\")" should not set the property value
Fail e.style['content'] = "url(\"https://www.example.com/picture.svg\") \"hello\" / no-open-quote" should not set the property value
Fail e.style['content'] = "url(\"https://www.example.com/picture.svg\") \"hello\" / no-close-quote" should not set the property value
Fail e.style['content'] = "url(\"https://www.example.com/picture.svg\") \"hello\" / \"hi\" no-close-quote" should not set the property value
Pass e.style['content'] = "open-quote / url(\"https://www.example.com/picture.svg\")" should not set the property value
Pass e.style['content'] = "open-quote / no-open-quote" should not set the property value
Pass e.style['content'] = "open-quote / no-close-quote" should not set the property value
Pass e.style['content'] = "open-quote / \"hi\" no-close-quote" should not set the property value
Pass e.style['content'] = "close-quote / url(\"https://www.example.com/picture.svg\")" should not set the property value
Pass e.style['content'] = "close-quote / no-open-quote" should not set the property value
Pass e.style['content'] = "close-quote / no-close-quote" should not set the property value
Pass e.style['content'] = "close-quote / \"hi\" no-close-quote" should not set the property value
Pass e.style['content'] = "no-open-quote / url(\"https://www.example.com/picture.svg\")" should not set the property value
Pass e.style['content'] = "no-open-quote / no-open-quote" should not set the property value
Pass e.style['content'] = "no-open-quote / no-close-quote" should not set the property value
Pass e.style['content'] = "no-open-quote / \"hi\" no-close-quote" should not set the property value
Pass e.style['content'] = "no-close-quote / url(\"https://www.example.com/picture.svg\")" should not set the property value
Pass e.style['content'] = "no-close-quote / no-open-quote" should not set the property value
Pass e.style['content'] = "no-close-quote / no-close-quote" should not set the property value
Pass e.style['content'] = "no-close-quote / \"hi\" no-close-quote" should not set the property value
Pass e.style['content'] = "counter(counter-name) / url(\"https://www.example.com/picture.svg\")" should not set the property value
Pass e.style['content'] = "counter(counter-name) / no-open-quote" should not set the property value
Pass e.style['content'] = "counter(counter-name) / no-close-quote" should not set the property value
Pass e.style['content'] = "counter(counter-name) / \"hi\" no-close-quote" should not set the property value
Pass e.style['content'] = "counter(counter-name, counter-style) / url(\"https://www.example.com/picture.svg\")" should not set the property value
Pass e.style['content'] = "counter(counter-name, counter-style) / no-open-quote" should not set the property value
Pass e.style['content'] = "counter(counter-name, counter-style) / no-close-quote" should not set the property value
Pass e.style['content'] = "counter(counter-name, counter-style) / \"hi\" no-close-quote" should not set the property value
Pass e.style['content'] = "counters(counter-name, \".\") / url(\"https://www.example.com/picture.svg\")" should not set the property value
Pass e.style['content'] = "counters(counter-name, \".\") / no-open-quote" should not set the property value
Pass e.style['content'] = "counters(counter-name, \".\") / no-close-quote" should not set the property value
Pass e.style['content'] = "counters(counter-name, \".\") / \"hi\" no-close-quote" should not set the property value
Pass e.style['content'] = "counters(counter-name, \".\", counter-style) / url(\"https://www.example.com/picture.svg\")" should not set the property value
Pass e.style['content'] = "counters(counter-name, \".\", counter-style) / no-open-quote" should not set the property value
Pass e.style['content'] = "counters(counter-name, \".\", counter-style) / no-close-quote" should not set the property value
Pass e.style['content'] = "counters(counter-name, \".\", counter-style) / \"hi\" no-close-quote" should not set the property value
Pass e.style['content'] = "url(\"https://www.example.com/picture.svg\") / url(\"https://www.example.com/picture.svg\")" should not set the property value
Pass e.style['content'] = "url(\"https://www.example.com/picture.svg\") / no-open-quote" should not set the property value
Pass e.style['content'] = "url(\"https://www.example.com/picture.svg\") / no-close-quote" should not set the property value
Pass e.style['content'] = "url(\"https://www.example.com/picture.svg\") / \"hi\" no-close-quote" should not set the property value
Pass e.style['content'] = "\"hello\" / url(\"https://www.example.com/picture.svg\")" should not set the property value
Pass e.style['content'] = "\"hello\" / no-open-quote" should not set the property value
Pass e.style['content'] = "\"hello\" / no-close-quote" should not set the property value
Pass e.style['content'] = "\"hello\" / \"hi\" no-close-quote" should not set the property value
Pass e.style['content'] = "\"hello\" \"world\" / url(\"https://www.example.com/picture.svg\")" should not set the property value
Pass e.style['content'] = "\"hello\" \"world\" / no-open-quote" should not set the property value
Pass e.style['content'] = "\"hello\" \"world\" / no-close-quote" should not set the property value
Pass e.style['content'] = "\"hello\" \"world\" / \"hi\" no-close-quote" should not set the property value
Pass e.style['content'] = "counter(counter-name) \"potato\" / url(\"https://www.example.com/picture.svg\")" should not set the property value
Pass e.style['content'] = "counter(counter-name) \"potato\" / no-open-quote" should not set the property value
Pass e.style['content'] = "counter(counter-name) \"potato\" / no-close-quote" should not set the property value
Pass e.style['content'] = "counter(counter-name) \"potato\" / \"hi\" no-close-quote" should not set the property value
Pass e.style['content'] = "counters(counter-name, \".\") \"potato\" / url(\"https://www.example.com/picture.svg\")" should not set the property value
Pass e.style['content'] = "counters(counter-name, \".\") \"potato\" / no-open-quote" should not set the property value
Pass e.style['content'] = "counters(counter-name, \".\") \"potato\" / no-close-quote" should not set the property value
Pass e.style['content'] = "counters(counter-name, \".\") \"potato\" / \"hi\" no-close-quote" should not set the property value
Pass e.style['content'] = "\"(\" counters(counter-name, \".\", counter-style) \")\" / url(\"https://www.example.com/picture.svg\")" should not set the property value
Pass e.style['content'] = "\"(\" counters(counter-name, \".\", counter-style) \")\" / no-open-quote" should not set the property value
Pass e.style['content'] = "\"(\" counters(counter-name, \".\", counter-style) \")\" / no-close-quote" should not set the property value
Pass e.style['content'] = "\"(\" counters(counter-name, \".\", counter-style) \")\" / \"hi\" no-close-quote" should not set the property value
Pass e.style['content'] = "open-quote \"hello\" \"world\" close-quote / url(\"https://www.example.com/picture.svg\")" should not set the property value
Pass e.style['content'] = "open-quote \"hello\" \"world\" close-quote / no-open-quote" should not set the property value
Pass e.style['content'] = "open-quote \"hello\" \"world\" close-quote / no-close-quote" should not set the property value
Pass e.style['content'] = "open-quote \"hello\" \"world\" close-quote / \"hi\" no-close-quote" should not set the property value
Pass e.style['content'] = "url(\"https://www.example.com/picture.svg\") \"hello\" / url(\"https://www.example.com/picture.svg\")" should not set the property value
Pass e.style['content'] = "url(\"https://www.example.com/picture.svg\") \"hello\" / no-open-quote" should not set the property value
Pass e.style['content'] = "url(\"https://www.example.com/picture.svg\") \"hello\" / no-close-quote" should not set the property value
Pass e.style['content'] = "url(\"https://www.example.com/picture.svg\") \"hello\" / \"hi\" no-close-quote" should not set the property value