chromium/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer.cc

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/no_destructor.h"
#include "base/task/single_thread_task_executor.h"
#include "components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.h"
#include "components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.h"
#include "mojo/core/embedder/embedder.h"
#include "testing/libfuzzer/libfuzzer_exports.h"
#include "testing/libfuzzer/proto/lpm_interface.h"

#include "components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer.pb.h"

namespace {

struct Env {
 public:
  Env() {
    mojo::core::Init();

    // Run fuzzer with the flag --dump-to-png[=dir-name] to dump the browser
    // display into PNG files for debugging purposes.
    base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
    auto png_dir_path =
        command_line->HasSwitch("dump-to-png")
            ? std::optional<base::FilePath>(
                  command_line->GetSwitchValuePath("dump-to-png"))
            : std::nullopt;

    // Re-initialize logging in order to pick up any command-line parameters
    // (such as --v=1 to enable verbose logging).
    logging::LoggingSettings settings;
    settings.logging_dest =
        logging::LOG_TO_SYSTEM_DEBUG_LOG | logging::LOG_TO_STDERR;
    logging::InitLogging(settings);

    browser_process = std::make_unique<viz::FuzzerBrowserProcess>(png_dir_path);
  }
  ~Env() = default;

  std::unique_ptr<viz::FuzzerBrowserProcess> browser_process;

 private:
  base::SingleThreadTaskExecutor single_thread_task_executor_;

  // Instantiation needed to make histogram macros in the SubmitCompositorFrame
  // flow work when verbosity is on.
  base::AtExitManager exit_manager_;
};

}  // namespace

extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
  base::CommandLine::Init(*argc, *argv);
  return 0;
}

DEFINE_BINARY_PROTO_FUZZER(
    const viz::proto::CompositorRenderPass& render_pass_spec) {
  static base::NoDestructor<Env> env;

  viz::FuzzedData fuzzed_frame =
      viz::BuildFuzzedCompositorFrame(render_pass_spec);

  env->browser_process->EmbedFuzzedCompositorFrame(
      std::move(fuzzed_frame.frame), std::move(fuzzed_frame.allocated_bitmaps));
}