[RWS] Add CHECK that no set is a singleton
The RWS parser *should* uphold this invariant, but making this invariant explicit in the type's ctor allows our fuzzers to tell us if they are able to break the invariant. Change-Id: I89c25321bf97096740dbecd5c900bc0f1a61e391 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5122551 Auto-Submit: Chris Fredrickson <cfredric@chromium.org> Commit-Queue: Sam LeDoux <sledoux@chromium.org> Reviewed-by: Sam LeDoux <sledoux@chromium.org> Cr-Commit-Position: refs/heads/main@{#1238146}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
af54d2f0ed
commit
3f6dcdc661
chrome/browser/top_level_storage_access_api
net/first_party_sets
14
chrome/browser/top_level_storage_access_api/top_level_storage_access_permission_context_unittest.cc
14
chrome/browser/top_level_storage_access_api/top_level_storage_access_permission_context_unittest.cc
@ -39,7 +39,7 @@ GURL GetTopLevelURL() {
|
||||
}
|
||||
|
||||
GURL GetRequesterURL() {
|
||||
return GURL("https://requester.example.com");
|
||||
return GURL("https://requester.com");
|
||||
}
|
||||
|
||||
GURL GetDummyEmbeddingUrl() {
|
||||
@ -198,14 +198,16 @@ class TopLevelStorageAccessPermissionContextAPIWithFirstPartySetsTest
|
||||
void SetUp() override {
|
||||
TopLevelStorageAccessPermissionContextTestAPIEnabledTest::SetUp();
|
||||
|
||||
// Create a FPS with https://requester.example.com as the member and
|
||||
// https://embedder.example.com as the primary.
|
||||
const net::SchemefulSite top_level(GetTopLevelURL());
|
||||
first_party_sets_handler_.SetGlobalSets(net::GlobalFirstPartySets(
|
||||
base::Version("1.2.3"),
|
||||
/*entries=*/
|
||||
{{net::SchemefulSite(GetRequesterURL()),
|
||||
{net::FirstPartySetEntry(net::SchemefulSite(GetTopLevelURL()),
|
||||
net::SiteType::kAssociated, 0)}}},
|
||||
{
|
||||
{net::SchemefulSite(GetRequesterURL()),
|
||||
net::FirstPartySetEntry(top_level, net::SiteType::kAssociated, 0)},
|
||||
{top_level, net::FirstPartySetEntry(
|
||||
top_level, net::SiteType::kPrimary, absl::nullopt)},
|
||||
},
|
||||
/*aliases=*/{}));
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "net/first_party_sets/global_first_party_sets.h"
|
||||
|
||||
#include <set>
|
||||
#include <tuple>
|
||||
|
||||
#include "base/containers/contains.h"
|
||||
@ -89,14 +90,15 @@ GlobalFirstPartySets::GlobalFirstPartySets(
|
||||
aliases_(std::move(aliases)),
|
||||
manual_config_(std::move(manual_config)),
|
||||
manual_aliases_(std::move(manual_aliases)) {
|
||||
if (public_sets_version_.IsValid()) {
|
||||
CHECK(base::ranges::all_of(aliases_, [&](const auto& pair) {
|
||||
return entries_.contains(pair.second);
|
||||
}));
|
||||
} else {
|
||||
if (!public_sets_version_.IsValid()) {
|
||||
CHECK(entries_.empty());
|
||||
CHECK(aliases_.empty());
|
||||
}
|
||||
|
||||
CHECK(base::ranges::all_of(aliases_, [&](const auto& pair) {
|
||||
return entries_.contains(pair.second);
|
||||
}));
|
||||
CHECK(!ContainsSingleton());
|
||||
}
|
||||
|
||||
GlobalFirstPartySets::GlobalFirstPartySets(GlobalFirstPartySets&&) = default;
|
||||
@ -205,6 +207,8 @@ void GlobalFirstPartySets::ApplyManuallySpecifiedSet(
|
||||
/*replacement_sets=*/{manual_entries},
|
||||
/*addition_sets=*/{}));
|
||||
manual_aliases_ = std::move(manual_aliases);
|
||||
|
||||
CHECK(!ContainsSingleton());
|
||||
}
|
||||
|
||||
void GlobalFirstPartySets::UnsafeSetManualConfig(
|
||||
@ -476,6 +480,28 @@ void GlobalFirstPartySets::ForEachAlias(
|
||||
}
|
||||
}
|
||||
|
||||
bool GlobalFirstPartySets::ContainsSingleton() const {
|
||||
std::set<SchemefulSite> possible_singletons;
|
||||
std::set<SchemefulSite> not_singletons;
|
||||
|
||||
ForEachEffectiveSetEntry(
|
||||
nullptr,
|
||||
[&](const SchemefulSite& site, const FirstPartySetEntry& entry) -> bool {
|
||||
if (!not_singletons.contains(entry.primary())) {
|
||||
if (site == entry.primary()) {
|
||||
possible_singletons.insert(entry.primary());
|
||||
} else {
|
||||
not_singletons.insert(entry.primary());
|
||||
possible_singletons.erase(entry.primary());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
return !possible_singletons.empty();
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const GlobalFirstPartySets& sets) {
|
||||
os << "{entries = {";
|
||||
for (const auto& [site, entry] : sets.entries_) {
|
||||
|
@ -172,6 +172,10 @@ class NET_EXPORT GlobalFirstPartySets {
|
||||
void ForEachAlias(base::FunctionRef<void(const SchemefulSite&,
|
||||
const SchemefulSite&)> f) const;
|
||||
|
||||
// Returns true iff this instance contains a singleton set (a set with only
|
||||
// one site).
|
||||
bool ContainsSingleton() const;
|
||||
|
||||
// The version associated with the component_updater-provided public sets.
|
||||
// This may be invalid if the "First-Party Sets" component has not been
|
||||
// installed yet, or has been corrupted. Entries and aliases from invalid
|
||||
|
@ -133,12 +133,15 @@ TEST_F(GlobalFirstPartySetsTest, FindEntry_Exists) {
|
||||
|
||||
TEST_F(GlobalFirstPartySetsTest, FindEntry_NoNormalization) {
|
||||
SchemefulSite https_example(GURL("https://example.test"));
|
||||
SchemefulSite associated(GURL("https://associated.test"));
|
||||
SchemefulSite wss_example(GURL("wss://example.test"));
|
||||
FirstPartySetEntry entry(https_example, SiteType::kPrimary, absl::nullopt);
|
||||
FirstPartySetEntry assoc_entry(https_example, SiteType::kAssociated, 0);
|
||||
|
||||
EXPECT_THAT(GlobalFirstPartySets(kVersion,
|
||||
{
|
||||
{https_example, entry},
|
||||
{associated, assoc_entry},
|
||||
},
|
||||
{})
|
||||
.FindEntry(wss_example, FirstPartySetsContextConfig()),
|
||||
@ -147,7 +150,9 @@ TEST_F(GlobalFirstPartySetsTest, FindEntry_NoNormalization) {
|
||||
|
||||
TEST_F(GlobalFirstPartySetsTest, FindEntry_ExistsViaOverride) {
|
||||
SchemefulSite example(GURL("https://example.test"));
|
||||
SchemefulSite associated(GURL("https://associated.test"));
|
||||
FirstPartySetEntry public_entry(example, SiteType::kPrimary, absl::nullopt);
|
||||
FirstPartySetEntry assoc_entry(example, SiteType::kAssociated, 0);
|
||||
FirstPartySetEntry override_entry(example, SiteType::kAssociated, 1);
|
||||
|
||||
FirstPartySetsContextConfig config(
|
||||
@ -156,6 +161,7 @@ TEST_F(GlobalFirstPartySetsTest, FindEntry_ExistsViaOverride) {
|
||||
EXPECT_THAT(GlobalFirstPartySets(kVersion,
|
||||
{
|
||||
{example, public_entry},
|
||||
{associated, assoc_entry},
|
||||
},
|
||||
{})
|
||||
.FindEntry(example, config),
|
||||
@ -164,7 +170,9 @@ TEST_F(GlobalFirstPartySetsTest, FindEntry_ExistsViaOverride) {
|
||||
|
||||
TEST_F(GlobalFirstPartySetsTest, FindEntry_RemovedViaOverride) {
|
||||
SchemefulSite example(GURL("https://example.test"));
|
||||
SchemefulSite associated(GURL("https://associated.test"));
|
||||
FirstPartySetEntry public_entry(example, SiteType::kPrimary, absl::nullopt);
|
||||
FirstPartySetEntry assoc_entry(example, SiteType::kAssociated, 0);
|
||||
|
||||
FirstPartySetsContextConfig config(
|
||||
{{example, net::FirstPartySetEntryOverride()}});
|
||||
@ -172,6 +180,7 @@ TEST_F(GlobalFirstPartySetsTest, FindEntry_RemovedViaOverride) {
|
||||
EXPECT_THAT(GlobalFirstPartySets(kVersion,
|
||||
{
|
||||
{example, public_entry},
|
||||
{associated, assoc_entry},
|
||||
},
|
||||
{})
|
||||
.FindEntry(example, config),
|
||||
|
Reference in New Issue
Block a user