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
content / renderer / content_security_policy_util_fuzzer.cc [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/342213636): Remove this and spanify to fix the errors.
#pragma allow_unsafe_buffers
#endif
// Configure:
// # tools/mb/mb.py gen -m chromium.fuzz -b 'Libfuzzer Upload Linux ASan' out/libfuzzer
// Build:
// # autoninja -C out/libfuzzer content_security_policy_util_fuzzer
// Run:
// # ./out/libfuzzer/content_security_policy_util_fuzzer
//
// For more details, see
// https://chromium.googlesource.com/chromium/src/+/main/testing/libfuzzer/README.md
#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/i18n/icu_util.h"
#include "base/strings/string_util.h"
#include "base/test/test_timeouts.h"
#include "content/public/test/blink_test_environment.h"
#include "content/renderer/content_security_policy_util.h"
#include "services/network/public/cpp/content_security_policy/content_security_policy.h"
#include "services/network/public/mojom/content_security_policy.mojom-forward.h"
namespace {
// This is similar to blink::BlinkFuzzerTestSupport, which we can't import from
// content.
class Environment {
public:
Environment() {
// Note: we don't tear anything down here after an iteration of the fuzzer
// is complete, this is for efficiency. We rerun the fuzzer with the same
// environment as the previous iteration.
base::AtExitManager at_exit;
CHECK(base::i18n::InitializeICU());
base::CommandLine::Init(0, nullptr);
TestTimeouts::Initialize();
blink_environment_.SetUp();
}
~Environment() {}
private:
content::BlinkTestEnvironment blink_environment_;
};
} // namespace
namespace content {
// Entry point for LibFuzzer. This function uses |data| to create a
// network::mojom::ContentSecurityPolicy |csp|, and then checks that the
// composition of BuildContentSecurityPolicy and ToWebContentSecurityPolicy is
// the identity on |csp|.
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
static Environment environment = Environment();
// We need two pieces of input: a URL and a CSP string. Split |data| in two at
// the first whitespace.
const uint8_t* it = data;
for (; it < data + size; it++) {
if (base::IsAsciiWhitespace(*reinterpret_cast<const char*>(it))) {
it++;
break;
}
}
if (it == data + size) {
// Not much point in going on with an empty CSP string.
return EXIT_SUCCESS;
}
if (it - data > 250) {
// Origins should not be too long. The fuzzer will run oom otherwise.
return EXIT_SUCCESS;
}
std::string raw_url(reinterpret_cast<const char*>(data), it - 1 - data);
std::string raw_csp(reinterpret_cast<const char*>(it), size - (it - data));
if (blink::WebString::FromUTF8(raw_url).Utf8() != raw_url ||
blink::WebString::FromUTF8(raw_csp).Utf8() != raw_csp) {
// The back-and-forth conversion can only work for valid utf8 input.
return EXIT_SUCCESS;
}
GURL parsed_url(raw_url);
if (!parsed_url.is_valid()) {
return EXIT_SUCCESS;
}
static const uint8_t kEnforcementBit = 0x01;
static const uint8_t kSourceBit1 = 0x02;
// Generate pseudo-random |header_type| and |header_source|.
network::mojom::ContentSecurityPolicyType header_type =
data[0] & kEnforcementBit
? network::mojom::ContentSecurityPolicyType::kEnforce
: network::mojom::ContentSecurityPolicyType::kReport;
network::mojom::ContentSecurityPolicySource header_source =
data[0] & kSourceBit1
? network::mojom::ContentSecurityPolicySource::kMeta
: network::mojom::ContentSecurityPolicySource::kHTTP;
// Parse the Content Security Policy string.
std::vector<network::mojom::ContentSecurityPolicyPtr> csp =
network::ParseContentSecurityPolicies(raw_csp, header_type, header_source,
GURL(raw_url));
if (csp.size() > 0) {
network::mojom::ContentSecurityPolicyPtr converted_csp =
BuildContentSecurityPolicy(ToWebContentSecurityPolicy(csp[0]->Clone()));
CHECK(converted_csp->Equals(*csp[0]));
}
return EXIT_SUCCESS;
}
} // namespace content
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
return content::LLVMFuzzerTestOneInput(data, size);
}