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 |