Index: third_party/WebKit/Source/platform/TextCodecFuzzer.cpp |
diff --git a/third_party/WebKit/Source/platform/TextCodecFuzzer.cpp b/third_party/WebKit/Source/platform/TextCodecFuzzer.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c39dc671a0190f2015722017d32fc3e2d281bbf0 |
--- /dev/null |
+++ b/third_party/WebKit/Source/platform/TextCodecFuzzer.cpp |
@@ -0,0 +1,95 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "wtf/text/TextCodec.h" |
+ |
+#include "platform/testing/BlinkFuzzerTestSupport.h" |
+#include "platform/testing/FuzzedDataProvider.h" |
+#include "wtf/text/CString.h" |
+#include "wtf/text/TextEncoding.h" |
+#include "wtf/text/TextEncodingRegistry.h" |
+ |
+using namespace blink; |
+ |
+// TODO(jsbell): This fuzzes code in wtf/ but has dependencies on platform/, |
+// so it must live in the latter directory. Once wtf/ moves into platform/wtf |
+// this should move there as well. |
+ |
+WTF::FlushBehavior kFlushBehavior[] = {WTF::DoNotFlush, WTF::FetchEOF, |
+ WTF::DataEOF}; |
+ |
+WTF::UnencodableHandling kUnencodableHandlingOptions[] = { |
+ WTF::QuestionMarksForUnencodables, WTF::EntitiesForUnencodables, |
+ WTF::URLEncodedEntitiesForUnencodables, |
+ WTF::CSSEncodedEntitiesForUnencodables}; |
+ |
+class TextCodecFuzzHarness {}; |
+extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) { |
+ InitializeBlinkFuzzTest(argc, argv); |
+ return 0; |
+} |
+ |
+// Fuzzer for WTF::TextCodec. |
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { |
+ // The fuzzer picks 3 bytes off the end of the data to initialize metadata, so |
+ // abort if the input is smaller than that. |
+ if (size < 3) |
+ return 0; |
+ |
+ // TODO(csharrison): When crbug.com/701825 is resolved, add the rest of the |
+ // text codecs. |
+ |
+ // Initializes the codec map. |
+ static const WTF::TextEncoding encoding = WTF::TextEncoding( |
+#if defined(UTF_8) |
+ "UTF-8" |
+#elif defined(WINDOWS_1252) |
+ "windows-1252" |
+#endif |
+ ""); |
+ |
+ FuzzedDataProvider fuzzedData(data, size); |
+ |
+ // Initialize metadata using the fuzzed data. |
+ bool stopOnError = fuzzedData.ConsumeBool(); |
+ WTF::UnencodableHandling unencodableHandling = |
+ fuzzedData.PickValueInArray(kUnencodableHandlingOptions); |
+ WTF::FlushBehavior flushBehavior = |
+ fuzzedData.PickValueInArray(kFlushBehavior); |
+ |
+ // Now, use the rest of the fuzzy data to stress test decoding and encoding. |
+ const CString byteString = fuzzedData.ConsumeRemainingBytes(); |
+ std::unique_ptr<TextCodec> codec = newTextCodec(encoding); |
+ |
+ // Treat as bytes-off-the-wire. |
+ bool sawError; |
+ const String decoded = codec->decode(byteString.data(), byteString.length(), |
+ flushBehavior, stopOnError, sawError); |
+ |
+ // Treat as blink 8-bit string (latin1). |
+ if (size % sizeof(LChar) == 0) { |
+ std::unique_ptr<TextCodec> codec = newTextCodec(encoding); |
+ codec->encode(reinterpret_cast<const LChar*>(byteString.data()), |
+ byteString.length() / sizeof(LChar), unencodableHandling); |
+ } |
+ |
+ // Treat as blink 16-bit string (utf-16) if there are an even number of bytes. |
+ if (size % sizeof(UChar) == 0) { |
+ std::unique_ptr<TextCodec> codec = newTextCodec(encoding); |
+ codec->encode(reinterpret_cast<const UChar*>(byteString.data()), |
+ byteString.length() / sizeof(UChar), unencodableHandling); |
+ } |
+ |
+ if (decoded.isNull()) |
+ return 0; |
+ |
+ // Round trip the bytes (aka encode the decoded bytes). |
+ if (decoded.is8Bit()) { |
+ codec->encode(decoded.characters8(), decoded.length(), unencodableHandling); |
+ } else { |
+ codec->encode(decoded.characters16(), decoded.length(), |
+ unencodableHandling); |
+ } |
+ return 0; |
+} |