• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/350788890): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9 
10 #include "base/at_exit.h"
11 #include "base/check_op.h"
12 #include "base/i18n/icu_util.h"
13 #include "base/no_destructor.h"
14 #include "url/gurl.h"
15 
16 struct TestCase {
TestCaseTestCase17   TestCase() { CHECK(base::i18n::InitializeICU()); }
18 
19   // used by ICU integration.
20   base::AtExitManager at_exit_manager;
21 };
22 
23 TestCase* test_case = new TestCase();
24 
25 // Checks that GURL's canonicalization is idempotent. This can help discover
26 // issues like https://crbug.com/1128999.
CheckIdempotency(const GURL & url)27 void CheckIdempotency(const GURL& url) {
28   if (!url.is_valid())
29     return;
30   const std::string& spec = url.spec();
31   GURL recanonicalized(spec);
32   CHECK(recanonicalized.is_valid());
33   CHECK_EQ(spec, recanonicalized.spec());
34 }
35 
36 // Checks that |url.spec()| is preserved across a call to ReplaceComponents with
37 // zero replacements, which is effectively a copy. This can help discover issues
38 // like https://crbug.com/1075515.
CheckReplaceComponentsPreservesSpec(const GURL & url)39 void CheckReplaceComponentsPreservesSpec(const GURL& url) {
40   static const base::NoDestructor<GURL::Replacements> no_op;
41   GURL copy = url.ReplaceComponents(*no_op);
42   CHECK_EQ(url.is_valid(), copy.is_valid());
43   if (url.is_valid()) {
44     CHECK_EQ(url.spec(), copy.spec());
45   }
46 }
47 
48 // Entry point for LibFuzzer.
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)49 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
50   if (size < 1)
51     return 0;
52   {
53     std::string_view string_piece_input(reinterpret_cast<const char*>(data),
54                                         size);
55     const GURL url_from_string_piece(string_piece_input);
56     CheckIdempotency(url_from_string_piece);
57     CheckReplaceComponentsPreservesSpec(url_from_string_piece);
58   }
59   // Test for std::u16string_view if size is even.
60   if (size % sizeof(char16_t) == 0) {
61     std::u16string_view string_piece_input16(
62         reinterpret_cast<const char16_t*>(data), size / sizeof(char16_t));
63     const GURL url_from_string_piece16(string_piece_input16);
64     CheckIdempotency(url_from_string_piece16);
65     CheckReplaceComponentsPreservesSpec(url_from_string_piece16);
66   }
67   // Resolve relative url tests.
68   {
69     size_t size_t_bytes = sizeof(size_t);
70     if (size < size_t_bytes + 1) {
71       return 0;
72     }
73     size_t relative_size =
74         *reinterpret_cast<const size_t*>(data) % (size - size_t_bytes);
75     std::string relative_string(
76         reinterpret_cast<const char*>(data + size_t_bytes), relative_size);
77     std::string_view string_piece_part_input(
78         reinterpret_cast<const char*>(data + size_t_bytes + relative_size),
79         size - relative_size - size_t_bytes);
80     const GURL url_from_string_piece_part(string_piece_part_input);
81     CheckIdempotency(url_from_string_piece_part);
82     CheckReplaceComponentsPreservesSpec(url_from_string_piece_part);
83 
84     std::ignore = url_from_string_piece_part.Resolve(relative_string);
85 
86     if (relative_size % sizeof(char16_t) == 0) {
87       std::u16string relative_string16(
88           reinterpret_cast<const char16_t*>(data + size_t_bytes),
89           relative_size / sizeof(char16_t));
90       std::ignore = url_from_string_piece_part.Resolve(relative_string16);
91     }
92   }
93   return 0;
94 }
95