tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

check.cc (11934B)


      1 // Copyright 2020 The Chromium Authors
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/check.h"
      6 
      7 #include "base/check_op.h"
      8 #include "base/debug/alias.h"
      9 #include "base/debug/dump_without_crashing.h"
     10 #include "base/feature_list.h"
     11 #include "base/features.h"
     12 #include "base/logging.h"
     13 #include "base/thread_annotations.h"
     14 #include "build/build_config.h"
     15 
     16 #if !defined(MOZ_SANDBOX)
     17 #if !BUILDFLAG(IS_NACL)
     18 #include "base/debug/crash_logging.h"
     19 #endif  // !BUILDFLAG(IS_NACL)
     20 #endif
     21 
     22 namespace logging {
     23 
     24 namespace {
     25 
     26 #if !defined(MOZ_SANDBOX)
     27 void DumpWithoutCrashing(LogMessage* log_message,
     28                         const base::Location& location) {
     29  // Copy the LogMessage message to stack memory to make sure it can be
     30  // recovered in crash dumps. This is easier to recover in minidumps than crash
     31  // keys during local debugging.
     32  DEBUG_ALIAS_FOR_CSTR(log_message_str, log_message->BuildCrashString().c_str(),
     33                       1024);
     34 
     35  // Report from the same location at most once every 30 days (unless the
     36  // process has died). This attempts to prevent us from flooding ourselves with
     37  // repeat reports for the same bug.
     38  base::debug::DumpWithoutCrashing(location, base::Days(30));
     39 }
     40 #endif
     41 
     42 void NotReachedDumpWithoutCrashing(LogMessage* log_message,
     43                                   const base::Location& location) {
     44 #if !defined(MOZ_SANDBOX)
     45 #if !BUILDFLAG(IS_NACL)
     46  SCOPED_CRASH_KEY_STRING1024("Logging", "NOTREACHED_MESSAGE",
     47                              log_message->BuildCrashString());
     48 #endif  // !BUILDFLAG(IS_NACL)
     49  DumpWithoutCrashing(log_message, location);
     50 #endif
     51 }
     52 
     53 void DCheckDumpWithoutCrashing(LogMessage* log_message,
     54                               const base::Location& location) {
     55 #if !defined(MOZ_SANDBOX)
     56 #if !BUILDFLAG(IS_NACL)
     57  SCOPED_CRASH_KEY_STRING1024("Logging", "DCHECK_MESSAGE",
     58                              log_message->BuildCrashString());
     59 #endif  // !BUILDFLAG(IS_NACL)
     60  DumpWithoutCrashing(log_message, location);
     61 #endif
     62 }
     63 
     64 void DumpWillBeCheckDumpWithoutCrashing(LogMessage* log_message,
     65                                        const base::Location& location) {
     66 #if !defined(MOZ_SANDBOX)
     67 #if !BUILDFLAG(IS_NACL)
     68  SCOPED_CRASH_KEY_STRING1024("Logging", "DUMP_WILL_BE_CHECK_MESSAGE",
     69                              log_message->BuildCrashString());
     70 #endif  // !BUILDFLAG(IS_NACL)
     71  DumpWithoutCrashing(log_message, location);
     72 #endif
     73 }
     74 
     75 class NotReachedLogMessage : public LogMessage {
     76 public:
     77  NotReachedLogMessage(const base::Location& location, LogSeverity severity)
     78      : LogMessage(location.file_name(), location.line_number(), severity),
     79        location_(location) {}
     80  ~NotReachedLogMessage() override {
     81    if (severity() != logging::LOGGING_FATAL) {
     82      NotReachedDumpWithoutCrashing(this, location_);
     83    }
     84  }
     85 
     86 private:
     87  const base::Location location_;
     88 };
     89 
     90 class DCheckLogMessage : public LogMessage {
     91 public:
     92  using LogMessage::LogMessage;
     93  DCheckLogMessage(const base::Location& location, LogSeverity severity)
     94      : LogMessage(location.file_name(), location.line_number(), severity),
     95        location_(location) {}
     96  ~DCheckLogMessage() override {
     97    if (severity() != logging::LOGGING_FATAL) {
     98      DCheckDumpWithoutCrashing(this, location_);
     99    }
    100  }
    101 
    102 private:
    103  const base::Location location_;
    104 };
    105 
    106 class DumpWillBeCheckLogMessage : public LogMessage {
    107 public:
    108  using LogMessage::LogMessage;
    109  DumpWillBeCheckLogMessage(const base::Location& location,
    110                            LogSeverity severity)
    111      : LogMessage(location.file_name(), location.line_number(), severity),
    112        location_(location) {}
    113  ~DumpWillBeCheckLogMessage() override {
    114    if (severity() != logging::LOGGING_FATAL) {
    115      DumpWillBeCheckDumpWithoutCrashing(this, location_);
    116    }
    117  }
    118 
    119 private:
    120  const base::Location location_;
    121 };
    122 
    123 #if BUILDFLAG(IS_WIN)
    124 class DCheckWin32ErrorLogMessage : public Win32ErrorLogMessage {
    125 public:
    126  DCheckWin32ErrorLogMessage(const base::Location& location,
    127                             LogSeverity severity,
    128                             SystemErrorCode err)
    129      : Win32ErrorLogMessage(location.file_name(),
    130                             location.line_number(),
    131                             severity,
    132                             err),
    133        location_(location) {}
    134  ~DCheckWin32ErrorLogMessage() override {
    135    if (severity() != logging::LOGGING_FATAL) {
    136      DCheckDumpWithoutCrashing(this, location_);
    137    }
    138  }
    139 
    140 private:
    141  const base::Location location_;
    142 };
    143 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
    144 class DCheckErrnoLogMessage : public ErrnoLogMessage {
    145 public:
    146  DCheckErrnoLogMessage(const base::Location& location,
    147                        LogSeverity severity,
    148                        SystemErrorCode err)
    149      : ErrnoLogMessage(location.file_name(),
    150                        location.line_number(),
    151                        severity,
    152                        err),
    153        location_(location) {}
    154  ~DCheckErrnoLogMessage() override {
    155    if (severity() != logging::LOGGING_FATAL) {
    156      DCheckDumpWithoutCrashing(this, location_);
    157    }
    158  }
    159 
    160 private:
    161  const base::Location location_;
    162 };
    163 #endif  // BUILDFLAG(IS_WIN)
    164 
    165 }  // namespace
    166 
    167 CheckError CheckError::Check(const char* condition,
    168                             const base::Location& location) {
    169  auto* const log_message = new LogMessage(
    170      location.file_name(), location.line_number(), LOGGING_FATAL);
    171  log_message->stream() << "Check failed: " << condition << ". ";
    172  return CheckError(log_message);
    173 }
    174 
    175 CheckError CheckError::CheckOp(char* log_message_str,
    176                               const base::Location& location) {
    177  auto* const log_message = new LogMessage(
    178      location.file_name(), location.line_number(), LOGGING_FATAL);
    179  log_message->stream() << log_message_str;
    180  free(log_message_str);
    181  return CheckError(log_message);
    182 }
    183 
    184 CheckError CheckError::DCheck(const char* condition,
    185                              const base::Location& location) {
    186  auto* const log_message = new DCheckLogMessage(location, LOGGING_DCHECK);
    187  log_message->stream() << "Check failed: " << condition << ". ";
    188  return CheckError(log_message);
    189 }
    190 
    191 CheckError CheckError::DCheckOp(char* log_message_str,
    192                                const base::Location& location) {
    193  auto* const log_message = new DCheckLogMessage(
    194      location.file_name(), location.line_number(), LOGGING_DCHECK);
    195  log_message->stream() << log_message_str;
    196  free(log_message_str);
    197  return CheckError(log_message);
    198 }
    199 
    200 CheckError CheckError::DumpWillBeCheck(const char* condition,
    201                                       const base::Location& location) {
    202  auto* const log_message = new DumpWillBeCheckLogMessage(
    203      location, DCHECK_IS_ON() ? LOGGING_DCHECK : LOGGING_ERROR);
    204  log_message->stream() << "Check failed: " << condition << ". ";
    205  return CheckError(log_message);
    206 }
    207 
    208 CheckError CheckError::DumpWillBeCheckOp(char* log_message_str,
    209                                         const base::Location& location) {
    210  auto* const log_message = new DumpWillBeCheckLogMessage(
    211      location, DCHECK_IS_ON() ? LOGGING_DCHECK : LOGGING_ERROR);
    212  log_message->stream() << log_message_str;
    213  free(log_message_str);
    214  return CheckError(log_message);
    215 }
    216 
    217 CheckError CheckError::PCheck(const char* condition,
    218                              const base::Location& location) {
    219  SystemErrorCode err_code = logging::GetLastSystemErrorCode();
    220 #if BUILDFLAG(IS_WIN)
    221  auto* const log_message = new Win32ErrorLogMessage(
    222      location.file_name(), location.line_number(), LOGGING_FATAL, err_code);
    223 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
    224  auto* const log_message = new ErrnoLogMessage(
    225      location.file_name(), location.line_number(), LOGGING_FATAL, err_code);
    226 #endif
    227  log_message->stream() << "Check failed: " << condition << ". ";
    228  return CheckError(log_message);
    229 }
    230 
    231 CheckError CheckError::PCheck(const base::Location& location) {
    232  return PCheck("", location);
    233 }
    234 
    235 CheckError CheckError::DPCheck(const char* condition,
    236                               const base::Location& location) {
    237  SystemErrorCode err_code = logging::GetLastSystemErrorCode();
    238 #if BUILDFLAG(IS_WIN)
    239  auto* const log_message =
    240      new DCheckWin32ErrorLogMessage(location, LOGGING_DCHECK, err_code);
    241 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
    242  auto* const log_message =
    243      new DCheckErrnoLogMessage(location, LOGGING_DCHECK, err_code);
    244 #endif
    245  log_message->stream() << "Check failed: " << condition << ". ";
    246  return CheckError(log_message);
    247 }
    248 
    249 CheckError CheckError::DumpWillBeNotReachedNoreturn(
    250    const base::Location& location) {
    251  auto* const log_message = new DumpWillBeCheckLogMessage(
    252      location, DCHECK_IS_ON() ? LOGGING_DCHECK : LOGGING_ERROR);
    253  log_message->stream() << "NOTREACHED hit. ";
    254  return CheckError(log_message);
    255 }
    256 
    257 CheckError CheckError::NotImplemented(const char* function,
    258                                      const base::Location& location) {
    259  auto* const log_message = new LogMessage(
    260      location.file_name(), location.line_number(), LOGGING_ERROR);
    261  log_message->stream() << "Not implemented reached in " << function;
    262  return CheckError(log_message);
    263 }
    264 
    265 std::ostream& CheckError::stream() {
    266  return log_message_->stream();
    267 }
    268 
    269 CheckError::~CheckError() {
    270  // TODO(crbug.com/1409729): Consider splitting out CHECK from DCHECK so that
    271  // the destructor can be marked [[noreturn]] and we don't need to check
    272  // severity in the destructor.
    273  const bool is_fatal = log_message_->severity() == LOGGING_FATAL;
    274  // Note: This function ends up in crash stack traces. If its full name
    275  // changes, the crash server's magic signature logic needs to be updated.
    276  // See cl/306632920.
    277  delete log_message_;
    278 
    279  // Make sure we crash even if LOG(FATAL) has been overridden.
    280  // TODO(crbug.com/1409729): Remove severity checking in the destructor when
    281  // LOG(FATAL) is [[noreturn]] and can't be overridden.
    282  if (is_fatal) {
    283    base::ImmediateCrash();
    284  }
    285 }
    286 
    287 NotReachedError NotReachedError::NotReached(const base::Location& location) {
    288  const LogSeverity severity = []() {
    289 #if !defined(MOZ_SANDBOX)
    290    // NOTREACHED() instances may be hit before base::FeatureList is enabled.
    291    if (base::FeatureList::GetInstance() &&
    292        base::FeatureList::IsEnabled(base::features::kNotReachedIsFatal)) {
    293      return LOGGING_FATAL;
    294    }
    295 #endif
    296    return DCHECK_IS_ON() ? LOGGING_DCHECK : LOGGING_ERROR;
    297  }();
    298  auto* const log_message = new NotReachedLogMessage(location, severity);
    299 
    300  // TODO(pbos): Consider a better message for NotReached(), this is here to
    301  // match existing behavior + test expectations.
    302  log_message->stream() << "Check failed: false. ";
    303  return NotReachedError(log_message);
    304 }
    305 
    306 void NotReachedError::TriggerNotReached() {
    307  // This triggers a NOTREACHED() error as the returned NotReachedError goes out
    308  // of scope.
    309  NotReached()
    310      << "NOTREACHED log messages are omitted in official builds. Sorry!";
    311 }
    312 
    313 NotReachedError::~NotReachedError() = default;
    314 
    315 NotReachedNoreturnError::NotReachedNoreturnError(const base::Location& location)
    316    : CheckError([location]() {
    317        auto* const log_message = new LogMessage(
    318            location.file_name(), location.line_number(), LOGGING_FATAL);
    319        log_message->stream() << "NOTREACHED hit. ";
    320        return log_message;
    321      }()) {}
    322 
    323 // Note: This function ends up in crash stack traces. If its full name changes,
    324 // the crash server's magic signature logic needs to be updated. See
    325 // cl/306632920.
    326 NotReachedNoreturnError::~NotReachedNoreturnError() {
    327  delete log_message_;
    328 
    329  // Make sure we die if we haven't.
    330  // TODO(crbug.com/1409729): Replace this with NOTREACHED_NORETURN() once
    331  // LOG(FATAL) is [[noreturn]].
    332  base::ImmediateCrash();
    333 }
    334 
    335 void RawCheckFailure(const char* message) {
    336  RawLog(LOGGING_FATAL, message);
    337  __builtin_unreachable();
    338 }
    339 
    340 }  // namespace logging