LibWeb: Salt ancestor filter hashes by selector component
Separate ancestor filter hashes for tag names, ids, classes, and attributes. This avoids false positives where identical strings in different selector component kinds satisfy each other, while keeping the filter conservative.
This commit is contained in:
parent
bc5d153e60
commit
0b2a5ac143
3 changed files with 46 additions and 7 deletions
35
Libraries/LibWeb/CSS/AncestorFilter.h
Normal file
35
Libraries/LibWeb/CSS/AncestorFilter.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2026-present, the Ladybird developers.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Types.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
// Separate otherwise identical string hashes by selector component kind,
|
||||
// e.g. `.article` versus `<article>`.
|
||||
static constexpr u32 ancestor_filter_hash_for_tag_name(u32 hash)
|
||||
{
|
||||
return hash * 13;
|
||||
}
|
||||
|
||||
static constexpr u32 ancestor_filter_hash_for_id(u32 hash)
|
||||
{
|
||||
return hash * 17;
|
||||
}
|
||||
|
||||
static constexpr u32 ancestor_filter_hash_for_class(u32 hash)
|
||||
{
|
||||
return hash * 19;
|
||||
}
|
||||
|
||||
static constexpr u32 ancestor_filter_hash_for_attribute(u32 hash)
|
||||
{
|
||||
return hash * 23;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
#include "Selector.h"
|
||||
#include <AK/GenericShorthands.h>
|
||||
#include <AK/NeverDestroyed.h>
|
||||
#include <LibWeb/CSS/AncestorFilter.h>
|
||||
#include <LibWeb/CSS/CSSStyleRule.h>
|
||||
#include <LibWeb/CSS/Parser/ErrorReporter.h>
|
||||
#include <LibWeb/CSS/Serialize.h>
|
||||
|
|
@ -201,14 +202,16 @@ void Selector::collect_ancestor_hashes()
|
|||
Vector<u32> hashes;
|
||||
switch (simple_selector.type) {
|
||||
case SimpleSelector::Type::Id:
|
||||
hashes.append(ancestor_filter_hash_for_id(simple_selector.name().hash()));
|
||||
break;
|
||||
case SimpleSelector::Type::Class:
|
||||
hashes.append(simple_selector.name().hash());
|
||||
hashes.append(ancestor_filter_hash_for_class(simple_selector.name().hash()));
|
||||
break;
|
||||
case SimpleSelector::Type::TagName:
|
||||
hashes.append(simple_selector.qualified_name().name.lowercase_name.hash());
|
||||
hashes.append(ancestor_filter_hash_for_tag_name(simple_selector.qualified_name().name.lowercase_name.hash()));
|
||||
break;
|
||||
case SimpleSelector::Type::Attribute:
|
||||
hashes.append(simple_selector.attribute().qualified_name.name.lowercase_name.hash());
|
||||
hashes.append(ancestor_filter_hash_for_attribute(simple_selector.attribute().qualified_name.name.lowercase_name.hash()));
|
||||
break;
|
||||
case SimpleSelector::Type::PseudoClass: {
|
||||
auto const& pseudo_class = simple_selector.pseudo_class();
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include <LibWeb/Animations/AnimationEffect.h>
|
||||
#include <LibWeb/Animations/DocumentTimeline.h>
|
||||
#include <LibWeb/Bindings/PrincipalHostDefined.h>
|
||||
#include <LibWeb/CSS/AncestorFilter.h>
|
||||
#include <LibWeb/CSS/AnimationEvent.h>
|
||||
#include <LibWeb/CSS/CSSAnimation.h>
|
||||
#include <LibWeb/CSS/CSSContainerRule.h>
|
||||
|
|
@ -3787,13 +3788,13 @@ NonnullRefPtr<StyleValue const> StyleComputer::compute_math_depth(NonnullRefPtr<
|
|||
|
||||
static void for_each_element_hash(DOM::Element const& element, auto callback)
|
||||
{
|
||||
callback(element.local_name().ascii_case_insensitive_hash());
|
||||
callback(ancestor_filter_hash_for_tag_name(element.local_name().ascii_case_insensitive_hash()));
|
||||
if (element.id().has_value())
|
||||
callback(element.id().value().hash());
|
||||
callback(ancestor_filter_hash_for_id(element.id().value().hash()));
|
||||
for (auto const& class_ : element.class_names())
|
||||
callback(class_.hash());
|
||||
callback(ancestor_filter_hash_for_class(class_.hash()));
|
||||
element.for_each_attribute([&](auto& attribute) {
|
||||
callback(attribute.name().ascii_case_insensitive_hash());
|
||||
callback(ancestor_filter_hash_for_attribute(attribute.name().ascii_case_insensitive_hash()));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue