diff options
Diffstat (limited to 'chromium/testing/libfuzzer/fuzzers/v8_fuzzer.cc')
-rw-r--r-- | chromium/testing/libfuzzer/fuzzers/v8_fuzzer.cc | 166 |
1 files changed, 0 insertions, 166 deletions
diff --git a/chromium/testing/libfuzzer/fuzzers/v8_fuzzer.cc b/chromium/testing/libfuzzer/fuzzers/v8_fuzzer.cc deleted file mode 100644 index d495d10818a..00000000000 --- a/chromium/testing/libfuzzer/fuzzers/v8_fuzzer.cc +++ /dev/null @@ -1,166 +0,0 @@ -// 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 <chrono> -#include <functional> -#include <iostream> -#include <mutex> -#include <thread> - -#include "base/logging.h" -#include "v8/include/libplatform/libplatform.h" -#include "v8/include/v8.h" - -using v8::MaybeLocal; -using std::ref; -using std::lock_guard; -using std::mutex; -using std::chrono::time_point; -using std::chrono::steady_clock; -using std::chrono::seconds; -using std::chrono::duration_cast; - -static const seconds kSleepSeconds(1); - -// Because of the sleep we do, the actual max will be: -// kSleepSeconds + kMaxExecutionSeconds. -// TODO(metzman): Determine if having such a short timeout causes too much -// indeterminism. -static const seconds kMaxExecutionSeconds(7); - -// Inspired by/copied from d8 code, this allocator will return nullptr when -// an allocation request is made that puts currently_allocated_ over -// kAllocationLimit (1 GB). Should handle the current allocations done by V8. -class MockArrayBufferAllocator : public v8::ArrayBuffer::Allocator { - std::unique_ptr<Allocator> allocator_ = - std::unique_ptr<Allocator>(NewDefaultAllocator()); - - const size_t kAllocationLimit = 1000 * 1024 * 1024; - // TODO(metzman): Determine if this approach where we keep track of state - // between runs is a good idea. Maybe we should simply prevent allocations - // over a certain size regardless of previous allocations. - size_t currently_allocated_; - mutex mtx_; - - public: - MockArrayBufferAllocator() - : v8::ArrayBuffer::Allocator(), currently_allocated_(0) {} - - void* Allocate(size_t length) override { - void* data = AllocateUninitialized(length); - return data == nullptr ? data : memset(data, 0, length); - } - - void* AllocateUninitialized(size_t length) override { - lock_guard<mutex> mtx_locker(mtx_); - if (length + currently_allocated_ > kAllocationLimit) { - return nullptr; - } - currently_allocated_ += length; - return malloc(length); - } - - void Free(void* ptr, size_t length) override { - lock_guard<mutex> mtx_locker(mtx_); - currently_allocated_ -= length; - // We need to free before we unlock, otherwise currently_allocated_ will - // be innacurate. - free(ptr); - } -}; - -void terminate_execution(v8::Isolate* isolate, - mutex& mtx, - bool& is_running, - time_point<steady_clock>& start_time) { - while (true) { - std::this_thread::sleep_for(kSleepSeconds); - mtx.lock(); - if (is_running) { - if (duration_cast<seconds>(steady_clock::now() - start_time) > - kMaxExecutionSeconds) { - isolate->TerminateExecution(); - is_running = false; - std::cout << "Terminated" << std::endl; - fflush(0); - } - } - mtx.unlock(); - } -} - -struct Environment { - Environment() { - platform_ = v8::platform::NewDefaultPlatform( - 0, v8::platform::IdleTaskSupport::kDisabled, - v8::platform::InProcessStackDumping::kDisabled, nullptr); - - v8::V8::InitializePlatform(platform_.get()); - v8::V8::Initialize(); - v8::Isolate::CreateParams create_params; - - create_params.array_buffer_allocator = &mock_arraybuffer_allocator; - isolate = v8::Isolate::New(create_params); - terminator_thread = std::thread(terminate_execution, isolate, ref(mtx), - ref(is_running), ref(start_time)); - } - MockArrayBufferAllocator mock_arraybuffer_allocator; - mutex mtx; - std::thread terminator_thread; - v8::Isolate* isolate; - std::unique_ptr<v8::Platform> platform_; - time_point<steady_clock> start_time; - bool is_running; -}; - -// Explicitly specify some attributes to avoid issues with the linker dead- -// stripping the following function on macOS, as it is not called directly -// by fuzz target. LibFuzzer runtime uses dlsym() to resolve that function. -extern "C" __attribute__((used)) __attribute__((visibility("default"))) int -LLVMFuzzerInitialize(int* argc, char*** argv) { - v8::V8::InitializeICUDefaultLocation((*argv)[0]); - v8::V8::InitializeExternalStartupData((*argv)[0]); - v8::V8::SetFlagsFromCommandLine(argc, *argv, true); - return 0; -} - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - static Environment* env = new Environment(); - - if (size < 1) - return 0; - - v8::Isolate::Scope isolate_scope(env->isolate); - v8::HandleScope handle_scope(env->isolate); - v8::Local<v8::Context> context = v8::Context::New(env->isolate); - v8::Context::Scope context_scope(context); - - std::string source_string = - std::string(reinterpret_cast<const char*>(data), size); - - MaybeLocal<v8::String> source_v8_string = v8::String::NewFromUtf8( - env->isolate, source_string.c_str(), v8::NewStringType::kNormal); - - if (source_v8_string.IsEmpty()) - return 0; - - v8::TryCatch try_catch(env->isolate); - MaybeLocal<v8::Script> script = - v8::Script::Compile(context, source_v8_string.ToLocalChecked()); - - if (script.IsEmpty()) - return 0; - - auto local_script = script.ToLocalChecked(); - env->mtx.lock(); - env->start_time = steady_clock::now(); - env->is_running = true; - env->mtx.unlock(); - - ALLOW_UNUSED_LOCAL(local_script->Run(context)); - - lock_guard<mutex> mtx_locker(env->mtx); - env->is_running = false; - return 0; -} |