1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "extensions/browser/api/declarative_net_request/ruleset_source.h"
#include <utility>
#include "base/containers/span.h"
#include "extensions/browser/api/declarative_net_request/constants.h"
#include "extensions/browser/api/declarative_net_request/flat_ruleset_indexer.h"
#include "extensions/browser/api/declarative_net_request/indexed_rule.h"
#include "extensions/browser/api/declarative_net_request/parse_info.h"
#include "extensions/browser/api/declarative_net_request/ruleset_matcher.h"
#include "extensions/browser/api/declarative_net_request/utils.h"
#include "extensions/common/api/declarative_net_request/constants.h"
#include "extensions/common/extension.h"
#include "third_party/flatbuffers/src/include/flatbuffers/flatbuffers.h"
#include "url/gurl.h"
namespace extensions::declarative_net_request {
RulesetSource::RulesetSource(RulesetID id,
size_t rule_count_limit,
ExtensionId extension_id,
bool enabled)
: id_(id),
rule_count_limit_(rule_count_limit),
extension_id_(std::move(extension_id)),
enabled_by_default_(enabled) {}
RulesetSource::~RulesetSource() = default;
RulesetSource::RulesetSource(RulesetSource&&) = default;
RulesetSource& RulesetSource::operator=(RulesetSource&&) = default;
ParseInfo RulesetSource::IndexRules(
std::vector<api::declarative_net_request::Rule> rules,
uint8_t parse_flags) const {
DCHECK_LE(rules.size(), rule_count_limit_);
// Only warnings or errors can be raised for problematic rules, not both.
DCHECK(!((parse_flags & ParseFlags::kRaiseErrorOnInvalidRules) &&
(parse_flags & ParseFlags::kRaiseWarningOnInvalidRules)));
DCHECK(!((parse_flags & ParseFlags::kRaiseErrorOnLargeRegexRules) &&
(parse_flags & ParseFlags::kRaiseWarningOnLargeRegexRules)));
FlatRulesetIndexer indexer;
std::vector<ParseInfo::RuleWarning> rule_warnings;
size_t rules_count = 0;
size_t regex_rules_count = 0;
{
std::set<int> id_set; // Ensure all ids are distinct.
const GURL base_url = Extension::GetBaseURLFromExtensionId(extension_id_);
for (auto& rule : rules) {
int rule_id = rule.id;
bool inserted = id_set.insert(rule_id).second;
if (!inserted) {
if (parse_flags & ParseFlags::kRaiseErrorOnInvalidRules) {
return ParseInfo(ParseResult::ERROR_DUPLICATE_IDS, rule_id);
}
if (parse_flags & ParseFlags::kRaiseWarningOnInvalidRules) {
rule_warnings.push_back(
{rule_id,
GetParseError(ParseResult::ERROR_DUPLICATE_IDS, rule_id)});
}
continue;
}
// Ignore rules that specify response header matching conditions if the
// feature is disabled.
// TODO(crbug.com/40727004): Enable this feature for all versions once
// initial testing is complete.
bool has_response_header_conditions =
rule.condition.response_headers.has_value() ||
rule.condition.excluded_response_headers.has_value();
if (has_response_header_conditions &&
!IsResponseHeaderMatchingEnabled()) {
continue;
}
IndexedRule indexed_rule;
ParseResult parse_result = IndexedRule::CreateIndexedRule(
std::move(rule), base_url, id(), &indexed_rule);
if (parse_result == ParseResult::ERROR_REGEX_TOO_LARGE) {
if (parse_flags & ParseFlags::kRaiseErrorOnLargeRegexRules) {
return ParseInfo(parse_result, rule_id);
}
if (parse_flags & ParseFlags::kRaiseWarningOnLargeRegexRules) {
rule_warnings.push_back(
{rule_id, GetParseError(parse_result, rule_id)});
}
continue;
}
if (parse_result != ParseResult::SUCCESS) {
if (parse_flags & ParseFlags::kRaiseErrorOnInvalidRules) {
return ParseInfo(parse_result, rule_id);
}
if (parse_flags & ParseFlags::kRaiseWarningOnInvalidRules) {
rule_warnings.push_back(
{rule_id, GetParseError(parse_result, rule_id)});
}
continue;
}
indexer.AddUrlRule(indexed_rule);
rules_count++;
if (indexed_rule.url_pattern_type ==
url_pattern_index::flat::UrlPatternType_REGEXP) {
regex_rules_count++;
}
}
}
flatbuffers::DetachedBuffer buffer = indexer.FinishAndReleaseBuffer();
int ruleset_checksum = GetChecksum(buffer);
return ParseInfo(rules_count, regex_rules_count, std::move(rule_warnings),
std::move(buffer), ruleset_checksum);
}
LoadRulesetResult RulesetSource::CreateVerifiedMatcher(
std::string data,
std::unique_ptr<RulesetMatcher>* matcher) const {
DCHECK(matcher);
flatbuffers::Verifier verifier(reinterpret_cast<const uint8_t*>(data.data()),
data.size());
// TODO(karandeepb): This should use a different LoadRulesetResult since it's
// not a checksum mismatch.
// This guarantees that no memory access will end up outside the buffer.
if (!flat::VerifyExtensionIndexedRulesetBuffer(verifier)) {
return LoadRulesetResult::kErrorChecksumMismatch;
}
*matcher =
std::make_unique<RulesetMatcher>(std::move(data), id(), extension_id());
return LoadRulesetResult::kSuccess;
}
} // namespace extensions::declarative_net_request
|