// Copyright 2020 The Fuchsia 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 "engine.h"

#include <lib/async-loop/default.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/status.h>

#include <string_view>

namespace fuzzing {
namespace {

using ::fuchsia::fuzzer::DataProvider;
using ::fuchsia::fuzzer::LlvmFuzzerPtr;
using ::fuchsia::fuzzer::Proxy;

// Usage message for direct invocation.
void Usage(const char *argv0) {
  std::cout << "usage: " << argv0 << " [options] [libFuzzer-options...]" << std::endl;
  std::cout << std::endl;
  std::cout << "options:" << std::endl;
  std::cout << "  -h|--help:         Print this message and exit." << std::endl;
  std::cout << "  --label=<label>:   Partition test input on data consumer label." << std::endl;
  std::cout << std::endl;
  std::cout << "Unrecognized items are passed to libFuzzer." << std::endl;
  exit(0);
}

// Stop the singleton when exiting.
void AtExit() { EngineImpl::GetInstance(false /* autoconnect */)->Stop(ZX_OK); }

}  // namespace

// Public methods

/* static */ EngineImpl *EngineImpl::GetInstance(bool autostart) {
  static EngineImpl engine(autostart);
  return &engine;
}

EngineImpl::~EngineImpl() {
  // Called on exit.
  Stop(ZX_OK);
}

zx_status_t EngineImpl::SetLlvmFuzzer(LlvmFuzzerPtr llvm_fuzzer) {
  // Set the pointer to the Proxy service.
  if (!llvm_fuzzer.is_bound()) {
    return ZX_ERR_INVALID_ARGS;
  }
  Stop(ZX_ERR_PEER_CLOSED);
  llvm_fuzzer_ = std::move(llvm_fuzzer);

  return ZX_OK;
}

void EngineImpl::Start(std::vector<std::string> options, StartCallback callback) {
  if (callback_) {
    FX_LOGS(ERROR) << "Already started.";
    callback(ZX_ERR_BAD_STATE);
    return;
  }
  if (!llvm_fuzzer_.is_bound()) {
    FX_LOGS(ERROR) << "LlvmFuzzer not set for engine.";
    callback(ZX_ERR_BAD_STATE);
    return;
  }
  callback_ = std::move(callback);

  zx::vmo vmo;
  data_provider_.Initialize(&vmo);

  llvm_fuzzer_->Initialize(std::move(vmo), std::move(options),
                           [this](int result, std::vector<std::string> modified) {
                             options_ = std::move(modified);
                             if (result != 0) {
                               Stop(result);
                             }
                             sync_completion_signal(&sync_);
                           });

  // libFuzzer's own std::atexit calls have run, so this will be the first exit callback invoked.
  std::atexit(::fuzzing::AtExit);
}

int EngineImpl::Initialize(int *argc, char ***argv) {
  if (!argv_.empty()) {
    FX_LOGS(ERROR) << "Already initialized.";
    return ZX_ERR_BAD_STATE;
  }

  // Extract the consumer labels.
  static constexpr std::string_view kLabel = "--label=";
  for (int i = 0; i < *argc; ++i) {
    std::string arg((*argv)[i]);
    if (arg == "-h" || arg == "--help") {
      Usage((*argv)[0]);
    } else if (arg.rfind(kLabel, 0) == 0) {
      data_provider_.AddConsumerLabel(arg.substr(kLabel.size()));
    } else {
      argv_.push_back((*argv)[i]);
    }
  }

  // Wait until the engine is started, then append the libFuzzer options.
  sync_completion_wait(&sync_, ZX_TIME_INFINITE);
  std::transform(options_.begin(), options_.end(), std::back_inserter(argv_),
                 [](const std::string &s) { return const_cast<char *>(s.c_str()); });
  *argc = argv_.size();
  *argv = &argv_[0];

  return ZX_OK;
}

int EngineImpl::TestOneInput(const uint8_t *data, size_t size) {
  if (!sync_completion_signaled(&sync_)) {
    FX_LOGS(ERROR) << "Not initialized.";
    return ZX_ERR_BAD_STATE;
  }

  zx_status_t status = data_provider_.PartitionTestInput(data, size);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "failed to start iteration: " << zx_status_get_string(status);
    return status;
  }

  sync_completion_t sync;
  llvm_fuzzer_->TestOneInput([&status, &sync](int result) {
    status = result;
    sync_completion_signal(&sync);
  });

  sync_completion_wait(&sync, ZX_TIME_INFINITE);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "fuzz target function returned non-zero status: " << status;
    return status;
  }

  if ((status = data_provider_.CompleteIteration()) != ZX_OK ||
      (status = coverage_.CompleteIteration()) != ZX_OK) {
    FX_LOGS(ERROR) << "failed to complete iteration: " << zx_status_get_string(status);
    return status;
  }
  return ZX_OK;
}

void EngineImpl::Stop(zx_status_t status) {
  coverage_.Reset();
  data_provider_.Reset();
  llvm_fuzzer_.Unbind();
  if (callback_) {
    callback_(status);
    callback_ = nullptr;
  }
  sync_completion_reset(&sync_);
}

// Private methods

EngineImpl::EngineImpl(bool autoconnect) {
  if (autoconnect) {
    loop_ = std::make_unique<async::Loop>(&kAsyncLoopConfigNoAttachToCurrentThread);
    FX_CHECK(context_->outgoing()->ServeFromStartupInfo(dispatcher_) == ZX_OK);
    context_->outgoing()->AddPublicService(coverage_.GetHandler());
    context_->outgoing()->AddPublicService(data_provider_.GetHandler());
    FX_CHECK(loop_->StartThread() == ZX_OK);
    auto svc = sys::ServiceDirectory::CreateFromNamespace();
    LlvmFuzzerPtr llvm_fuzzer;
    svc->Connect(llvm_fuzzer.NewRequest(loop_->dispatcher()));
    FX_CHECK(SetLlvmFuzzer(std::move(llvm_fuzzer)) == ZX_OK);
  }
}

void EngineImpl::UseContextImpl(std::unique_ptr<sys::ComponentContext> context) {
  Stop(ZX_OK);
  argv_.clear();
  context_ = std::move(context);
  context_->outgoing()->AddPublicService(coverage_.GetHandler());
  context_->outgoing()->AddPublicService(data_provider_.GetHandler());
}

}  // namespace fuzzing
