Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(728)

Unified Diff: third_party/WebKit/Source/bindings/core/v8/serialization/SerializedScriptValueFuzzer.cpp

Issue 2402503002: Add a fuzzer for V8ScriptValueDeserializer. (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/bindings/core/v8/serialization/SerializedScriptValueFuzzer.cpp
diff --git a/third_party/WebKit/Source/bindings/core/v8/serialization/SerializedScriptValueFuzzer.cpp b/third_party/WebKit/Source/bindings/core/v8/serialization/SerializedScriptValueFuzzer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..19ae6d2e367def8e9bb60a6b820c6d057f0d8419
--- /dev/null
+++ b/third_party/WebKit/Source/bindings/core/v8/serialization/SerializedScriptValueFuzzer.cpp
@@ -0,0 +1,110 @@
+// Copyright 2016 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 "bindings/core/v8/SerializedScriptValue.h"
+
+#include "bindings/core/v8/ScriptState.h"
+#include "core/dom/MessagePort.h"
+#include "core/frame/Settings.h"
+#include "core/testing/DummyPageHolder.h"
+#include "platform/RuntimeEnabledFeatures.h"
+#include "platform/testing/BlinkFuzzerTestSupport.h"
+#include "public/platform/WebBlobInfo.h"
+#include "public/platform/WebMessagePortChannel.h"
+#include "wtf/ByteOrder.h"
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <v8.h>
+
+using namespace blink;
+
+namespace {
+
+// Intentionally leaked during fuzzing.
+// See testing/libfuzzer/efficient_fuzzer.md.
+DummyPageHolder* pageHolder = nullptr;
+
+enum : uint32_t {
+ kFuzzMessagePorts = 1 << 0,
+ kFuzzBlobInfo = 1 << 1,
+};
+
+class WebMessagePortChannelImpl final : public WebMessagePortChannel {
+ public:
+ // WebMessagePortChannel
+ void setClient(WebMessagePortChannelClient* client) override {}
+ void destroy() override { delete this; }
+ void postMessage(const WebString&, WebMessagePortChannelArray*) {
+ NOTIMPLEMENTED();
+ }
+ bool tryGetMessage(WebString*, WebMessagePortChannelArray&) { return false; }
+};
+
+} // namespace
+
+extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
+ InitializeBlinkFuzzTest(argc, argv);
+ RuntimeEnabledFeatures::setV8BasedStructuredCloneEnabled(true);
+ pageHolder = DummyPageHolder::create().release();
+ pageHolder->frame().settings()->setScriptEnabled(true);
+ return 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ // Consume a 32-bit fuzzing flags field before the real input.
mmoroz 2016/10/07 14:16:38 Do you really want to consume 32-bit from the data
jbroman 2016/10/07 15:11:14 It's unintuitive to me why this is better; I would
mmoroz 2016/10/07 15:44:12 Yeah, that's a valid concern (I used to prefer thi
jbroman 2016/10/07 18:27:11 OK, switched to a hash. Thanks for the explanation
+ // This lets the fuzzer control whether message ports and blobs are provided.
+ uint32_t flags;
+ if (size < sizeof(flags))
+ return 0;
+ memcpy(&flags, data, sizeof(flags));
mmoroz 2016/10/07 14:16:38 Would you mind to use https://cs.chromium.org/chro
jbroman 2016/10/07 15:11:14 Ah, wasn't aware of it. base/ is ordinarily banned
+ data += sizeof(flags);
+ size -= sizeof(flags);
+ flags = ntohl(flags);
+
+ // Odd sizes are handled in various ways, depending how they arrive.
+ // Let's not worry about that case here.
+ if (size % sizeof(UChar))
+ return 0;
+
+ // If message ports are requested, make some.
+ MessagePortArray* messagePorts = nullptr;
+ if (flags & kFuzzMessagePorts) {
+ messagePorts = new MessagePortArray(3);
+ std::generate(messagePorts->begin(), messagePorts->end(), []() {
+ WebMessagePortChannelUniquePtr channel(new WebMessagePortChannelImpl());
+ MessagePort* port = MessagePort::create(pageHolder->document());
+ port->entangle(std::move(channel));
+ return port;
+ });
+ }
+
+ // If blobs are requested, make some.
+ WebBlobInfoArray blobInfoArray;
+ const WebBlobInfoArray* blobs = nullptr;
+ if (flags & kFuzzBlobInfo) {
+ blobInfoArray.emplaceAppend("d875dfc2-4505-461b-98fe-0cf6cc5eaf44",
+ "text/plain", 12);
+ blobInfoArray.emplaceAppend("d875dfc2-4505-461b-98fe-0cf6cc5eaf44",
+ "/native/path", "path", "text/plain");
+ blobs = &blobInfoArray;
mmoroz 2016/10/07 14:16:38 Looks like this is read-only: https://cs.chromium.
jbroman 2016/10/07 15:11:14 Done.
+ }
+
+ // Set up.
haraken 2016/10/07 02:14:53 Can you use V8TestingScope?
jbroman 2016/10/07 15:11:14 Since V8TestingScope is STACK_ALLOCATED, this woul
+ ScriptState* scriptState = ScriptState::forMainWorld(&pageHolder->frame());
+ v8::Isolate* isolate = scriptState->isolate();
+ ScriptState::Scope scope(scriptState);
+ v8::TryCatch tryCatch(isolate);
+
+ // Deserialize.
+ RefPtr<SerializedScriptValue> serializedScriptValue =
+ SerializedScriptValue::create(reinterpret_cast<const char*>(data), size);
+ serializedScriptValue->deserialize(isolate, messagePorts, blobs);
+
+ // Clean up.
+ CHECK(!tryCatch.HasCaught())
mmoroz 2016/10/07 14:16:38 Just to clarify: this is something we don't expect
jbroman 2016/10/07 15:11:14 Right. I'd like to know if an exception somehow es
+ << "deserialize() should return null rather than throwing an exception.";
+ return 0;
+}

Powered by Google App Engine
This is Rietveld 408576698