OLD | NEW |
| (Empty) |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "wtf/text/TextCodec.h" | |
6 | |
7 #include "platform/testing/BlinkFuzzerTestSupport.h" | |
8 #include "platform/testing/FuzzedDataProvider.h" | |
9 #include "wtf/text/CString.h" | |
10 #include "wtf/text/TextEncoding.h" | |
11 #include "wtf/text/TextEncodingRegistry.h" | |
12 | |
13 using namespace blink; | |
14 | |
15 // TODO(jsbell): This fuzzes code in wtf/ but has dependencies on platform/, | |
16 // so it must live in the latter directory. Once wtf/ moves into platform/wtf | |
17 // this should move there as well. | |
18 | |
19 WTF::FlushBehavior kFlushBehavior[] = {WTF::DoNotFlush, WTF::FetchEOF, | |
20 WTF::DataEOF}; | |
21 | |
22 WTF::UnencodableHandling kUnencodableHandlingOptions[] = { | |
23 WTF::QuestionMarksForUnencodables, WTF::EntitiesForUnencodables, | |
24 WTF::URLEncodedEntitiesForUnencodables, | |
25 WTF::CSSEncodedEntitiesForUnencodables}; | |
26 | |
27 class TextCodecFuzzHarness {}; | |
28 extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) { | |
29 InitializeBlinkFuzzTest(argc, argv); | |
30 return 0; | |
31 } | |
32 | |
33 // Fuzzer for WTF::TextCodec. | |
34 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { | |
35 // The fuzzer picks 3 bytes off the end of the data to initialize metadata, so | |
36 // abort if the input is smaller than that. | |
37 if (size < 3) | |
38 return 0; | |
39 | |
40 // Initializes the codec map. | |
41 static const WTF::TextEncoding encoding = WTF::TextEncoding( | |
42 #if defined(BIG5) | |
43 "Big5" | |
44 #elif defined(EUC_JP) | |
45 "EUC-JP" | |
46 #elif defined(EUC_KR) | |
47 "EUC-KR" | |
48 #elif defined(GBK) | |
49 "GBK" | |
50 #elif defined(IBM866) | |
51 "IBM866" | |
52 #elif defined(ISO_2022_JP) | |
53 "ISO-2022-JP" | |
54 #elif defined(ISO_8859_10) | |
55 "ISO-8859-10" | |
56 #elif defined(ISO_8859_13) | |
57 "ISO-8859-13" | |
58 #elif defined(ISO_8859_14) | |
59 "ISO-8859-14" | |
60 #elif defined(ISO_8859_15) | |
61 "ISO-8859-15" | |
62 #elif defined(ISO_8859_16) | |
63 "ISO-8859-16" | |
64 #elif defined(ISO_8859_2) | |
65 "ISO-8859-2" | |
66 #elif defined(ISO_8859_3) | |
67 "ISO-8859-3" | |
68 #elif defined(ISO_8859_4) | |
69 "ISO-8859-4" | |
70 #elif defined(ISO_8859_5) | |
71 "ISO-8859-5" | |
72 #elif defined(ISO_8859_6) | |
73 "ISO-8859-6" | |
74 #elif defined(ISO_8859_7) | |
75 "ISO-8859-7" | |
76 #elif defined(ISO_8859_8) | |
77 "ISO-8859-8" | |
78 #elif defined(ISO_8859_8_I) | |
79 "ISO-8859-8-I" | |
80 #elif defined(KOI8_R) | |
81 "KOI8-R" | |
82 #elif defined(KOI8_U) | |
83 "KOI8-U" | |
84 #elif defined(SHIFT_JIS) | |
85 "Shift_JIS" | |
86 #elif defined(UTF_16BE) | |
87 "UTF-16BE" | |
88 #elif defined(UTF_16LE) | |
89 "UTF-16LE" | |
90 #elif defined(UTF_32) | |
91 "UTF-32" | |
92 #elif defined(UTF_32BE) | |
93 "UTF-32BE" | |
94 #elif defined(UTF_32LE) | |
95 "UTF-32LE" | |
96 #elif defined(UTF_8) | |
97 "UTF-8" | |
98 #elif defined(GB18030) | |
99 "gb18030" | |
100 #elif defined(MACINTOSH) | |
101 "macintosh" | |
102 #elif defined(WINDOWS_1250) | |
103 "windows-1250" | |
104 #elif defined(WINDOWS_1251) | |
105 "windows-1251" | |
106 #elif defined(WINDOWS_1252) | |
107 "windows-1252" | |
108 #elif defined(WINDOWS_1253) | |
109 "windows-1253" | |
110 #elif defined(WINDOWS_1254) | |
111 "windows-1254" | |
112 #elif defined(WINDOWS_1255) | |
113 "windows-1255" | |
114 #elif defined(WINDOWS_1256) | |
115 "windows-1256" | |
116 #elif defined(WINDOWS_1257) | |
117 "windows-1257" | |
118 #elif defined(WINDOWS_1258) | |
119 "windows-1258" | |
120 #elif defined(WINDOWS_874) | |
121 "windows-874" | |
122 #elif defined(X_MAC_CYRILLIC) | |
123 "x-mac-cyrillic" | |
124 #elif defined(X_USER_DEFINED) | |
125 "x-user-defined" | |
126 #endif | |
127 ""); | |
128 | |
129 FuzzedDataProvider fuzzedData(data, size); | |
130 | |
131 // Initialize metadata using the fuzzed data. | |
132 bool stopOnError = fuzzedData.ConsumeBool(); | |
133 WTF::UnencodableHandling unencodableHandling = | |
134 fuzzedData.PickValueInArray(kUnencodableHandlingOptions); | |
135 WTF::FlushBehavior flushBehavior = | |
136 fuzzedData.PickValueInArray(kFlushBehavior); | |
137 | |
138 // Now, use the rest of the fuzzy data to stress test decoding and encoding. | |
139 const CString byteString = fuzzedData.ConsumeRemainingBytes(); | |
140 std::unique_ptr<TextCodec> codec = newTextCodec(encoding); | |
141 | |
142 // Treat as bytes-off-the-wire. | |
143 bool sawError; | |
144 const String decoded = codec->decode(byteString.data(), byteString.length(), | |
145 flushBehavior, stopOnError, sawError); | |
146 | |
147 // Treat as blink 8-bit string (latin1). | |
148 if (size % sizeof(LChar) == 0) { | |
149 std::unique_ptr<TextCodec> codec = newTextCodec(encoding); | |
150 codec->encode(reinterpret_cast<const LChar*>(byteString.data()), | |
151 byteString.length() / sizeof(LChar), unencodableHandling); | |
152 } | |
153 | |
154 // Treat as blink 16-bit string (utf-16) if there are an even number of bytes. | |
155 if (size % sizeof(UChar) == 0) { | |
156 std::unique_ptr<TextCodec> codec = newTextCodec(encoding); | |
157 codec->encode(reinterpret_cast<const UChar*>(byteString.data()), | |
158 byteString.length() / sizeof(UChar), unencodableHandling); | |
159 } | |
160 | |
161 if (decoded.isNull()) | |
162 return 0; | |
163 | |
164 // Round trip the bytes (aka encode the decoded bytes). | |
165 if (decoded.is8Bit()) { | |
166 codec->encode(decoded.characters8(), decoded.length(), unencodableHandling); | |
167 } else { | |
168 codec->encode(decoded.characters16(), decoded.length(), | |
169 unencodableHandling); | |
170 } | |
171 return 0; | |
172 } | |
OLD | NEW |