// Copyright 2018 The Crashpad Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "client/crashpad_client.h"

#include <dlfcn.h>
#include <setjmp.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <unistd.h>

#include "base/check_op.h"
#include "base/notreached.h"
#include "build/build_config.h"
#include "client/annotation.h"
#include "client/annotation_list.h"
#include "client/crash_report_database.h"
#include "client/crashpad_info.h"
#include "client/simulate_crash.h"
#include "gtest/gtest.h"
#include "snapshot/annotation_snapshot.h"
#include "snapshot/minidump/process_snapshot_minidump.h"
#include "snapshot/sanitized/sanitization_information.h"
#include "test/errors.h"
#include "test/multiprocess.h"
#include "test/multiprocess_exec.h"
#include "test/scoped_temp_dir.h"
#include "test/test_paths.h"
#include "util/file/file_io.h"
#include "util/file/filesystem.h"
#include "util/linux/exception_handler_client.h"
#include "util/linux/exception_information.h"
#include "util/linux/socket.h"
#include "util/misc/address_sanitizer.h"
#include "util/misc/address_types.h"
#include "util/misc/from_pointer_cast.h"
#include "util/misc/memory_sanitizer.h"
#include "util/posix/scoped_mmap.h"
#include "util/posix/signals.h"
#include "util/thread/thread.h"

#if BUILDFLAG(IS_ANDROID)
#include <android/set_abort_message.h>
#include "dlfcn_internal.h"

// Normally this comes from set_abort_message.h, but only at API level 21.
extern "C" void android_set_abort_message(const char* msg)
    __attribute__((weak));
#endif

namespace crashpad {
namespace test {
namespace {

enum class CrashType : uint32_t {
  kSimulated,
  kBuiltinTrap,
  kInfiniteRecursion,
  kSegvWithTagBits,
};

struct StartHandlerForSelfTestOptions {
  bool start_handler_at_crash;
  bool set_first_chance_handler;
  bool crash_non_main_thread;
  bool client_uses_signals;
  bool gather_indirectly_referenced_memory;
  CrashType crash_type;
};

class StartHandlerForSelfTest
    : public testing::TestWithParam<
          std::tuple<bool, bool, bool, bool, bool, CrashType>> {
 public:
  StartHandlerForSelfTest() = default;

  StartHandlerForSelfTest(const StartHandlerForSelfTest&) = delete;
  StartHandlerForSelfTest& operator=(const StartHandlerForSelfTest&) = delete;

  ~StartHandlerForSelfTest() = default;

  void SetUp() override {
    // MSAN requires that padding bytes have been initialized for structs that
    // are written to files.
    memset(&options_, 0, sizeof(options_));
    std::tie(options_.start_handler_at_crash,
             options_.set_first_chance_handler,
             options_.crash_non_main_thread,
             options_.client_uses_signals,
             options_.gather_indirectly_referenced_memory,
             options_.crash_type) = GetParam();
  }

  const StartHandlerForSelfTestOptions& Options() const { return options_; }

 private:
  StartHandlerForSelfTestOptions options_;
};

bool InstallHandler(CrashpadClient* client,
                    bool start_at_crash,
                    const base::FilePath& handler_path,
                    const base::FilePath& database_path,
                    const std::vector<base::FilePath>& attachments) {
  return start_at_crash
             ? client->StartHandlerAtCrash(handler_path,
                                           database_path,
                                           base::FilePath(),
                                           "",
                                           std::map<std::string, std::string>(),
                                           std::vector<std::string>(),
                                           attachments)
             : client->StartHandler(handler_path,
                                    database_path,
                                    base::FilePath(),
                                    "",
                                    std::map<std::string, std::string>(),
                                    std::vector<std::string>(),
                                    false,
                                    false,
                                    attachments);
}

constexpr char kTestAnnotationName[] = "name_of_annotation";
constexpr char kTestAnnotationValue[] = "value_of_annotation";
constexpr char kTestAttachmentName[] = "test_attachment";
constexpr char kTestAttachmentContent[] = "attachment_content";

#if BUILDFLAG(IS_ANDROID)
constexpr char kTestAbortMessage[] = "test abort message";
#endif

void ValidateAttachment(const CrashReportDatabase::UploadReport* report) {
  auto attachments = report->GetAttachments();
  ASSERT_EQ(attachments.size(), 1u);
  char buf[sizeof(kTestAttachmentContent)];
  attachments.at(kTestAttachmentName)->Read(buf, sizeof(buf));
  ASSERT_EQ(memcmp(kTestAttachmentContent, buf, sizeof(kTestAttachmentContent)),
            0);
}

void ValidateExtraMemory(const StartHandlerForSelfTestOptions& options,
                         const ProcessSnapshotMinidump& minidump) {
  // Verify that if we have an exception, then the code around the instruction
  // pointer is included in the extra memory.
  const ExceptionSnapshot* exception = minidump.Exception();
  if (exception == nullptr)
    return;
  uint64_t pc = exception->Context()->InstructionPointer();
  std::vector<const MemorySnapshot*> snippets = minidump.ExtraMemory();
  bool pc_found = false;
  for (const MemorySnapshot* snippet : snippets) {
    uint64_t start = snippet->Address();
    uint64_t end = start + snippet->Size();
    if (pc >= start && pc < end) {
      pc_found = true;
      break;
    }
  }
  EXPECT_EQ(pc_found, options.gather_indirectly_referenced_memory);

  if (options.crash_type == CrashType::kSegvWithTagBits) {
    EXPECT_EQ(exception->ExceptionAddress(), 0xefull << 56);
  }
}

void ValidateDump(const StartHandlerForSelfTestOptions& options,
                  const CrashReportDatabase::UploadReport* report) {
  ProcessSnapshotMinidump minidump_snapshot;
  ASSERT_TRUE(minidump_snapshot.Initialize(report->Reader()));

#if BUILDFLAG(IS_ANDROID)
  // This part of the test requires Q. The API level on Q devices will be 28
  // until the API is finalized, so we can't check API level yet. For now, test
  // for the presence of a libc symbol which was introduced in Q.
  if (crashpad::internal::Dlsym(RTLD_DEFAULT, "android_fdsan_close_with_tag")) {
    const auto& annotations = minidump_snapshot.AnnotationsSimpleMap();
    auto abort_message = annotations.find("abort_message");
    ASSERT_NE(annotations.end(), abort_message);
    EXPECT_EQ(kTestAbortMessage, abort_message->second);
  }
#endif
  ValidateAttachment(report);

  ValidateExtraMemory(options, minidump_snapshot);

  for (const ModuleSnapshot* module : minidump_snapshot.Modules()) {
    for (const AnnotationSnapshot& annotation : module->AnnotationObjects()) {
      if (static_cast<Annotation::Type>(annotation.type) !=
          Annotation::Type::kString) {
        continue;
      }

      if (annotation.name == kTestAnnotationName) {
        std::string value(
            reinterpret_cast<const char*>(annotation.value.data()),
            annotation.value.size());
        EXPECT_EQ(value, kTestAnnotationValue);
        return;
      }
    }
  }
  ADD_FAILURE();
}

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Winfinite-recursion"
// Clang (masquerading as gcc) is too smart, and removes the recursion
// otherwise. May need to change if either clang or another compiler becomes
// smarter.
#if defined(COMPILER_GCC)
__attribute__((noinline))
#endif
#if defined(__clang__)
__attribute__((optnone))
#endif
int RecurseInfinitely(int* ptr) {
  int buf[1 << 20];
  return *ptr + RecurseInfinitely(buf);
}
#pragma clang diagnostic pop

sigjmp_buf do_crash_sigjmp_env;

bool HandleCrashSuccessfully(int, siginfo_t*, ucontext_t*) {
  siglongjmp(do_crash_sigjmp_env, 1);
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunreachable-code-return"
  return true;
#pragma clang diagnostic pop
}

void DoCrash(const StartHandlerForSelfTestOptions& options,
             CrashpadClient* client) {
  if (sigsetjmp(do_crash_sigjmp_env, 1) != 0) {
    return;
  }

  switch (options.crash_type) {
    case CrashType::kSimulated: {
      CRASHPAD_SIMULATE_CRASH();
      break;
    }

    case CrashType::kBuiltinTrap: {
      __builtin_trap();
    }

    case CrashType::kInfiniteRecursion: {
      int val = 42;
      exit(RecurseInfinitely(&val));
    }

    case CrashType::kSegvWithTagBits: {
      volatile char* x = nullptr;
#ifdef __aarch64__
      x += 0xefull << 56;
#endif  // __aarch64__
      *x;
      break;
    }
  }
}

class ScopedAltSignalStack {
 public:
  ScopedAltSignalStack() = default;

  ScopedAltSignalStack(const ScopedAltSignalStack&) = delete;
  ScopedAltSignalStack& operator=(const ScopedAltSignalStack&) = delete;

  ~ScopedAltSignalStack() {
    if (stack_mem_.is_valid()) {
      stack_t stack;
      stack.ss_flags = SS_DISABLE;
      if (sigaltstack(&stack, nullptr) != 0) {
        ADD_FAILURE() << ErrnoMessage("sigaltstack");
      }
    }
  }

  void Initialize() {
    ScopedMmap local_stack_mem;
    const size_t stack_size = MINSIGSTKSZ;
    ASSERT_TRUE(local_stack_mem.ResetMmap(nullptr,
                                          stack_size,
                                          PROT_READ | PROT_WRITE,
                                          MAP_PRIVATE | MAP_ANONYMOUS,
                                          -1,
                                          0));

    stack_t stack;
    stack.ss_sp = local_stack_mem.addr();
    stack.ss_size = stack_size;
    stack.ss_flags = 0;
    ASSERT_EQ(sigaltstack(&stack, nullptr), 0) << ErrnoMessage("sigaltstack");
    stack_mem_.ResetAddrLen(local_stack_mem.release(), stack_size);
  }

 private:
  ScopedMmap stack_mem_;
};

class CrashThread : public Thread {
 public:
  CrashThread(const StartHandlerForSelfTestOptions& options,
              CrashpadClient* client)
      : client_signal_stack_(), options_(options), client_(client) {}

  CrashThread(const CrashThread&) = delete;
  CrashThread& operator=(const CrashThread&) = delete;

 private:
  void ThreadMain() override {
    // It is only necessary to call InitializeSignalStackForThread() once, but
    // should be harmless to call multiple times and durable against the client
    // using sigaltstack() either before or after it is called.
    CrashpadClient::InitializeSignalStackForThread();
    if (options_.client_uses_signals) {
      client_signal_stack_.Initialize();
    }
    CrashpadClient::InitializeSignalStackForThread();

    DoCrash(options_, client_);
  }

  ScopedAltSignalStack client_signal_stack_;
  const StartHandlerForSelfTestOptions& options_;
  CrashpadClient* client_;
};

CRASHPAD_CHILD_TEST_MAIN(StartHandlerForSelfTestChild) {
  FileHandle in = StdioFileHandle(StdioStream::kStandardInput);

  VMSize temp_dir_length;
  CheckedReadFileExactly(in, &temp_dir_length, sizeof(temp_dir_length));

  std::string temp_dir(temp_dir_length, '\0');
  CheckedReadFileExactly(in, &temp_dir[0], temp_dir_length);

  StartHandlerForSelfTestOptions options;
  CheckedReadFileExactly(in, &options, sizeof(options));

  ScopedAltSignalStack client_signal_stack;
  if (options.client_uses_signals) {
    client_signal_stack.Initialize();

    static Signals::OldActions old_actions;
    static Signals::Handler client_handler =
        [](int signo, siginfo_t* siginfo, void*) {
          FileHandle out = StdioFileHandle(StdioStream::kStandardOutput);
          char c = 0;
          WriteFile(out, &c, sizeof(c));

          Signals::RestoreHandlerAndReraiseSignalOnReturn(
              siginfo, old_actions.ActionForSignal(signo));
        };

    CHECK(Signals::InstallCrashHandlers(
        client_handler, SA_ONSTACK, &old_actions));
  }

  if (options.gather_indirectly_referenced_memory) {
    CrashpadInfo::GetCrashpadInfo()->set_gather_indirectly_referenced_memory(
        TriState::kEnabled, 1024 * 1024 * 4);
  }

  base::FilePath handler_path = TestPaths::Executable().DirName().Append(
      FILE_PATH_LITERAL("crashpad_handler"));

  crashpad::AnnotationList::Register();

  static StringAnnotation<32> test_annotation(kTestAnnotationName);
  test_annotation.Set(kTestAnnotationValue);

  const std::vector<base::FilePath> attachments = {
      base::FilePath(temp_dir).Append(kTestAttachmentName)};

  crashpad::CrashpadClient client;
  if (!InstallHandler(&client,
                      options.start_handler_at_crash,
                      handler_path,
                      base::FilePath(temp_dir),
                      attachments)) {
    return EXIT_FAILURE;
  }

  if (options.set_first_chance_handler) {
    client.SetFirstChanceExceptionHandler(HandleCrashSuccessfully);
  }

#if BUILDFLAG(IS_ANDROID)
  if (android_set_abort_message) {
    android_set_abort_message(kTestAbortMessage);
  }
#endif

  if (options.crash_non_main_thread) {
    CrashThread thread(options, &client);
    thread.Start();
    thread.Join();
  } else {
    DoCrash(options, &client);
  }

  return EXIT_SUCCESS;
}

class StartHandlerForSelfInChildTest : public MultiprocessExec {
 public:
  StartHandlerForSelfInChildTest(const StartHandlerForSelfTestOptions& options)
      : MultiprocessExec(), options_(options) {
    SetChildTestMainFunction("StartHandlerForSelfTestChild");
    if (!options.set_first_chance_handler) {
      switch (options.crash_type) {
        case CrashType::kSimulated:
          // kTerminationNormal, EXIT_SUCCESS
          break;
        case CrashType::kBuiltinTrap:
          SetExpectedChildTerminationBuiltinTrap();
          break;
        case CrashType::kInfiniteRecursion:
          SetExpectedChildTermination(TerminationReason::kTerminationSignal,
                                      SIGSEGV);
          break;
        case CrashType::kSegvWithTagBits:
          SetExpectedChildTermination(TerminationReason::kTerminationSignal,
                                      SIGSEGV);
      }
    }
  }

  StartHandlerForSelfInChildTest(const StartHandlerForSelfInChildTest&) =
      delete;
  StartHandlerForSelfInChildTest& operator=(
      const StartHandlerForSelfInChildTest&) = delete;

 private:
  void MultiprocessParent() override {
    ScopedTempDir temp_dir;
    VMSize temp_dir_length = temp_dir.path().value().size();
    ASSERT_TRUE(LoggingWriteFile(
        WritePipeHandle(), &temp_dir_length, sizeof(temp_dir_length)));
    ASSERT_TRUE(LoggingWriteFile(
        WritePipeHandle(), temp_dir.path().value().data(), temp_dir_length));
    ASSERT_TRUE(
        LoggingWriteFile(WritePipeHandle(), &options_, sizeof(options_)));

    FileWriter writer;
    base::FilePath test_attachment_path =
        temp_dir.path().Append(kTestAttachmentName);
    bool is_created = writer.Open(test_attachment_path,
                                  FileWriteMode::kCreateOrFail,
                                  FilePermissions::kOwnerOnly);
    ASSERT_TRUE(is_created);
    writer.Write(kTestAttachmentContent, sizeof(kTestAttachmentContent));
    writer.Close();

    if (options_.client_uses_signals && !options_.set_first_chance_handler &&
        options_.crash_type != CrashType::kSimulated) {
      // Wait for child's client signal handler.
      char c;
      EXPECT_TRUE(LoggingReadFileExactly(ReadPipeHandle(), &c, sizeof(c)));
    }

    // Wait for child to finish.
    CheckedReadFileAtEOF(ReadPipeHandle());

    auto database = CrashReportDatabase::Initialize(temp_dir.path());
    ASSERT_TRUE(database);

    std::vector<CrashReportDatabase::Report> reports;
    ASSERT_EQ(database->GetCompletedReports(&reports),
              CrashReportDatabase::kNoError);
    EXPECT_EQ(reports.size(), 0u);

    reports.clear();
    ASSERT_EQ(database->GetPendingReports(&reports),
              CrashReportDatabase::kNoError);

    bool report_expected = !options_.set_first_chance_handler ||
                           options_.crash_type == CrashType::kSimulated;
    ASSERT_EQ(reports.size(), report_expected ? 1u : 0u);

    if (!report_expected) {
      return;
    }

    std::unique_ptr<const CrashReportDatabase::UploadReport> report;
    ASSERT_EQ(database->GetReportForUploading(reports[0].uuid, &report),
              CrashReportDatabase::kNoError);
    ValidateDump(options_, report.get());
  }

  StartHandlerForSelfTestOptions options_;
};

TEST_P(StartHandlerForSelfTest, StartHandlerInChild) {
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
    defined(UNDEFINED_SANITIZER)
  if (Options().crash_type == CrashType::kInfiniteRecursion) {
    GTEST_SKIP();
  }
#endif  // defined(ADDRESS_SANITIZER)

  if (Options().crash_type == CrashType::kSegvWithTagBits) {
#if !defined(ARCH_CPU_ARM64)
    GTEST_SKIP() << "Testing for tag bits only exists on aarch64.";
#else
    struct utsname uname_info;
    ASSERT_EQ(uname(&uname_info), 0);
    ASSERT_NE(uname_info.release, nullptr);

    char* release = uname_info.release;
    unsigned major = strtoul(release, &release, 10);
    ASSERT_EQ(*release++, '.');
    unsigned minor = strtoul(release, nullptr, 10);

    if (major < 5 || (major == 5 && minor < 11)) {
      GTEST_SKIP() << "Linux kernel v" << uname_info.release
                   << " does not support SA_EXPOSE_TAGBITS";
    }
#endif  // !defined(ARCH_CPU_ARM64)
  }

  StartHandlerForSelfInChildTest test(Options());
  test.Run();
}

INSTANTIATE_TEST_SUITE_P(
    StartHandlerForSelfTestSuite,
    StartHandlerForSelfTest,
    testing::Combine(testing::Bool(),
                     testing::Bool(),
                     testing::Bool(),
                     testing::Bool(),
                     testing::Bool(),
                     testing::Values(CrashType::kSimulated,
                                     CrashType::kBuiltinTrap,
                                     CrashType::kInfiniteRecursion,
                                     CrashType::kSegvWithTagBits)));

// Test state for starting the handler for another process.
class StartHandlerForClientTest {
 public:
  StartHandlerForClientTest() = default;

  StartHandlerForClientTest(const StartHandlerForClientTest&) = delete;
  StartHandlerForClientTest& operator=(const StartHandlerForClientTest&) =
      delete;

  ~StartHandlerForClientTest() = default;

  bool Initialize(bool sanitize) {
    sanitize_ = sanitize;
    return UnixCredentialSocket::CreateCredentialSocketpair(&client_sock_,
                                                            &server_sock_);
  }

  bool StartHandlerOnDemand() {
    char c;
    if (!LoggingReadFileExactly(server_sock_.get(), &c, sizeof(c))) {
      ADD_FAILURE();
      return false;
    }

    base::FilePath handler_path = TestPaths::Executable().DirName().Append(
        FILE_PATH_LITERAL("crashpad_handler"));

    CrashpadClient client;
    if (!client.StartHandlerForClient(handler_path,
                                        temp_dir_.path(),
                                        base::FilePath(),
                                        "",
                                        std::map<std::string, std::string>(),
                                        std::vector<std::string>(),
                                        server_sock_.get())) {
      ADD_FAILURE();
      return false;
    }

    return true;
  }

  void ExpectReport() {
    auto database =
        CrashReportDatabase::InitializeWithoutCreating(temp_dir_.path());
    ASSERT_TRUE(database);

    std::vector<CrashReportDatabase::Report> reports;
    ASSERT_EQ(database->GetCompletedReports(&reports),
              CrashReportDatabase::kNoError);
    EXPECT_EQ(reports.size(), 0u);

    reports.clear();
    ASSERT_EQ(database->GetPendingReports(&reports),
              CrashReportDatabase::kNoError);
    if (sanitize_) {
      EXPECT_EQ(reports.size(), 0u);
    } else {
      EXPECT_EQ(reports.size(), 1u);
    }
  }

  bool InstallHandler() {
    auto signal_handler = SandboxedHandler::Get();
    return signal_handler->Initialize(client_sock_.get(), sanitize_);
  }

 private:
  // A signal handler that defers handler process startup to another, presumably
  // more privileged, process.
  class SandboxedHandler {
   public:
    SandboxedHandler(const SandboxedHandler&) = delete;
    SandboxedHandler& operator=(const SandboxedHandler&) = delete;

    static SandboxedHandler* Get() {
      static SandboxedHandler* instance = new SandboxedHandler();
      return instance;
    }

    bool Initialize(FileHandle client_sock, bool sanitize) {
      client_sock_ = client_sock;
      sanitize_ = sanitize;
      return Signals::InstallCrashHandlers(HandleCrash, 0, nullptr);
    }

   private:
    SandboxedHandler() = default;
    ~SandboxedHandler() = delete;

    static void HandleCrash(int signo, siginfo_t* siginfo, void* context) {
      auto state = Get();

      char c = 0;
      CHECK(LoggingWriteFile(state->client_sock_, &c, sizeof(c)));

      ExceptionInformation exception_information;
      exception_information.siginfo_address =
          FromPointerCast<decltype(exception_information.siginfo_address)>(
              siginfo);
      exception_information.context_address =
          FromPointerCast<decltype(exception_information.context_address)>(
              context);
      exception_information.thread_id = syscall(SYS_gettid);

      ExceptionHandlerProtocol::ClientInformation info;
      info.exception_information_address =
          FromPointerCast<decltype(info.exception_information_address)>(
              &exception_information);

      SanitizationInformation sanitization_info = {};
      if (state->sanitize_) {
        info.sanitization_information_address =
            FromPointerCast<VMAddress>(&sanitization_info);
        // Target a non-module address to prevent a crash dump.
        sanitization_info.target_module_address =
            FromPointerCast<VMAddress>(&sanitization_info);
      }

      ExceptionHandlerClient handler_client(state->client_sock_, false);
      CHECK_EQ(handler_client.RequestCrashDump(info), 0);

      Signals::RestoreHandlerAndReraiseSignalOnReturn(siginfo, nullptr);
    }

    FileHandle client_sock_;
    bool sanitize_;
  };

  ScopedTempDir temp_dir_;
  ScopedFileHandle client_sock_;
  ScopedFileHandle server_sock_;
  bool sanitize_;
};

// Tests starting the handler for a child process.
class StartHandlerForChildTest : public Multiprocess {
 public:
  StartHandlerForChildTest() = default;

  StartHandlerForChildTest(const StartHandlerForChildTest&) = delete;
  StartHandlerForChildTest& operator=(const StartHandlerForChildTest&) = delete;

  ~StartHandlerForChildTest() = default;

  bool Initialize(bool sanitize) {
    SetExpectedChildTerminationBuiltinTrap();
    return test_state_.Initialize(sanitize);
  }

 private:
  void MultiprocessParent() {
    ASSERT_TRUE(test_state_.StartHandlerOnDemand());

    // Wait for chlid to finish.
    CheckedReadFileAtEOF(ReadPipeHandle());

    test_state_.ExpectReport();
  }

  void MultiprocessChild() {
    CHECK(test_state_.InstallHandler());

    __builtin_trap();

    NOTREACHED();
  }

  StartHandlerForClientTest test_state_;
};

TEST(CrashpadClient, StartHandlerForChild) {
  StartHandlerForChildTest test;
  ASSERT_TRUE(test.Initialize(/* sanitize= */ false));
  test.Run();
}

TEST(CrashpadClient, SanitizedChild) {
  StartHandlerForChildTest test;
  ASSERT_TRUE(test.Initialize(/* sanitize= */ true));
  test.Run();
}

}  // namespace
}  // namespace test
}  // namespace crashpad
