File: ruleset_source.cc

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (147 lines) | stat: -rw-r--r-- 5,509 bytes parent folder | download | duplicates (7)
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