Separate check failure message parts more clearly.
This CL encompasses two changes:
1. Always end check failure messages with a period.
2. In fuzzing mode, replace the period with a semicolon.
For example:
CHECK(false);
Yields:
Check failed: false.
Or, with additional data streamed in:
CHECK(false) << "foo";
The output is:
Check failed: false. foo
In fuzzing mode, however, in a bid to help machines understand where
to draw the line between the compile-time static part ("false") and
the runtime-variable part ("foo"), we use a semicolon instead. It
seems quite difficult to manage to embed a semilicon in the
compile-time static part. Thus the examples above become:
Check failed: false;
Check failed: false; foo
Change-Id: Ia09851382f0d3207d0720d204cef26e223ade024
Bug: 443588668
Cq-Include-Trybots: luci.chromium.try:chromeos-x64-libfuzzer-asan-rel-tests,linux-x64-libfuzzer-asan-dbg-tests,linux-x64-libfuzzer-asan-rel-tests,linux-x64-libfuzzer-msan-rel-tests,linux-x64-libfuzzer-ubsan-rel-tests,linux-x86-libfuzzer-asan-rel-tests,mac-arm64-libfuzzer-asan-rel-tests,win-x64-libfuzzer-asan-rel-tests,linux-x64-centipede-asan-rel-tests
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6917708
Reviewed-by: Antonio Alphonse <alphonsea@google.com>
Commit-Queue: Antonio Alphonse <alphonsea@google.com>
Auto-Submit: Titouan Rigoudy <titouan@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1558298}
diff --git a/base/check.cc b/base/check.cc
index 8c274fef..d69a6aa 100644
--- a/base/check.cc
+++ b/base/check.cc
@@ -9,17 +9,51 @@
#include "base/check_op.h"
#include "base/check_version_internal.h"
#include "base/debug/alias.h"
+#include "base/debug/crash_logging.h"
#include "base/debug/dump_without_crashing.h"
#include "base/logging.h"
#include "base/thread_annotations.h"
#include "base/types/cxx23_to_underlying.h"
#include "build/build_config.h"
-#include "base/debug/crash_logging.h"
namespace logging {
namespace {
+// End check failure messages with a period, e.g.:
+//
+// CHECK(false);
+//
+// Yields:
+//
+// Check failed: false.
+//
+// Or, with additional data streamed in:
+//
+// CHECK(false) << "foo";
+//
+// The output is:
+//
+// Check failed: false. foo
+//
+// In fuzzing mode, however, in a bid to help machines understand where to draw
+// the line between the compile-time static part ("false") and the
+// runtime-variable part ("foo"), we use a semicolon instead. It seems quite
+// difficult to manage to embed a semilicon in the compile-time static part.
+// Thus the examples above become:
+//
+// Check failed: false;
+// Check failed: false; foo
+//
+// See crbug.com/443588668 for more details.
+constexpr char kCheckFailureMessageSeparator[] =
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ "; "
+#else
+ ". "
+#endif
+ ;
+
LogSeverity GetDumpSeverity() {
#if defined(OFFICIAL_BUILD)
return DCHECK_IS_ON() ? LOGGING_DCHECK : LOGGING_ERROR;
@@ -217,7 +251,8 @@
auto* const log_message = new CheckLogMessage(
location, GetCheckSeverity(fatal_milestone), fatal_milestone);
// TODO(pbos): Make this output CHECK instead of Check.
- log_message->stream() << "Check failed: " << condition << ". ";
+ log_message->stream() << "Check failed: " << condition
+ << kCheckFailureMessageSeparator;
return CheckError(log_message);
}
@@ -227,7 +262,8 @@
auto* const log_message = new CheckLogMessage(
location, GetCheckSeverity(fatal_milestone), fatal_milestone);
// TODO(pbos): Make this output CHECK instead of Check.
- log_message->stream() << "Check failed: " << log_message_str;
+ log_message->stream() << "Check failed: " << log_message_str
+ << kCheckFailureMessageSeparator;
free(log_message_str);
return log_message;
}
@@ -235,14 +271,16 @@
CheckError CheckError::DCheck(const char* condition,
const base::Location& location) {
auto* const log_message = new DCheckLogMessage(location);
- log_message->stream() << "DCHECK failed: " << condition << ". ";
+ log_message->stream() << "DCHECK failed: " << condition
+ << kCheckFailureMessageSeparator;
return CheckError(log_message);
}
LogMessage* CheckError::DCheckOp(char* log_message_str,
const base::Location& location) {
auto* const log_message = new DCheckLogMessage(location);
- log_message->stream() << "DCHECK failed: " << log_message_str;
+ log_message->stream() << "DCHECK failed: " << log_message_str
+ << kCheckFailureMessageSeparator;
free(log_message_str);
return log_message;
}
@@ -253,7 +291,8 @@
new CheckLogMessage(location, GetDumpSeverity(),
base::NotFatalUntil::NoSpecifiedMilestoneInternal);
// TODO(pbos): Make this output CHECK instead of Check.
- log_message->stream() << "Check failed: " << condition << ". ";
+ log_message->stream() << "Check failed: " << condition
+ << kCheckFailureMessageSeparator;
return CheckError(log_message);
}
@@ -263,7 +302,8 @@
new CheckLogMessage(location, GetDumpSeverity(),
base::NotFatalUntil::NoSpecifiedMilestoneInternal);
// TODO(pbos): Make this output CHECK instead of Check.
- log_message->stream() << "Check failed: " << log_message_str;
+ log_message->stream() << "Check failed: " << log_message_str
+ << kCheckFailureMessageSeparator;
free(log_message_str);
return log_message;
}
@@ -276,7 +316,8 @@
#elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
auto* const log_message = new DCheckErrnoLogMessage(location, err_code);
#endif
- log_message->stream() << "DCHECK failed: " << condition << ". ";
+ log_message->stream() << "DCHECK failed: " << condition
+ << kCheckFailureMessageSeparator;
return CheckError(log_message);
}
@@ -285,7 +326,8 @@
auto* const log_message = new LogMessage(
location.file_name(), location.line_number(), LOGGING_ERROR);
// TODO(pbos): Make this output NOTIMPLEMENTED instead of Not implemented.
- log_message->stream() << "Not implemented reached in " << function;
+ log_message->stream() << "Not implemented reached in " << function
+ << kCheckFailureMessageSeparator;
return CheckError(log_message);
}
@@ -332,7 +374,8 @@
new CheckLogMessage(location, LOGGING_FATAL,
base::NotFatalUntil::NoSpecifiedMilestoneInternal);
// TODO(pbos): Make this output CHECK instead of Check.
- log_message->stream() << "Check failed: " << condition << ". ";
+ log_message->stream() << "Check failed: " << condition
+ << kCheckFailureMessageSeparator;
return CheckNoreturnError(log_message);
}
@@ -342,7 +385,8 @@
new CheckLogMessage(location, LOGGING_FATAL,
base::NotFatalUntil::NoSpecifiedMilestoneInternal);
// TODO(pbos): Make this output CHECK instead of Check.
- log_message->stream() << "Check failed: " << log_message_str;
+ log_message->stream() << "Check failed: " << log_message_str
+ << kCheckFailureMessageSeparator;
free(log_message_str);
return log_message;
}
@@ -358,7 +402,8 @@
location.file_name(), location.line_number(), LOGGING_FATAL, err_code);
#endif
// TODO(pbos): Make this output CHECK instead of Check.
- log_message->stream() << "Check failed: " << condition << ". ";
+ log_message->stream() << "Check failed: " << condition
+ << kCheckFailureMessageSeparator;
return CheckNoreturnError(log_message);
}
diff --git a/base/check_unittest.cc b/base/check_unittest.cc
index ae5e0d0..06ca33e 100644
--- a/base/check_unittest.cc
+++ b/base/check_unittest.cc
@@ -177,9 +177,9 @@
EXPECT_CHECK("Check failed: false. foo", CHECK(false) << "foo");
double a = 2, b = 1;
- EXPECT_CHECK("Check failed: a < b (2.000000 vs. 1.000000)", CHECK_LT(a, b));
+ EXPECT_CHECK("Check failed: a < b (2.000000 vs. 1.000000). ", CHECK_LT(a, b));
- EXPECT_CHECK("Check failed: a < b (2.000000 vs. 1.000000)custom message",
+ EXPECT_CHECK("Check failed: a < b (2.000000 vs. 1.000000). custom message",
CHECK_LT(a, b) << "custom message");
}
@@ -189,29 +189,17 @@
std::string err =
logging::SystemErrorCodeToString(logging::GetLastSystemErrorCode());
- EXPECT_CHECK(
- "Check failed: fopen(file, \"r\") != nullptr."
- " : " +
- err,
- PCHECK(fopen(file, "r") != nullptr));
+ EXPECT_CHECK("Check failed: fopen(file, \"r\") != nullptr. : " + err,
+ PCHECK(fopen(file, "r") != nullptr));
- EXPECT_CHECK(
- "Check failed: fopen(file, \"r\") != nullptr."
- " foo: " +
- err,
- PCHECK(fopen(file, "r") != nullptr) << "foo");
+ EXPECT_CHECK("Check failed: fopen(file, \"r\") != nullptr. foo: " + err,
+ PCHECK(fopen(file, "r") != nullptr) << "foo");
- EXPECT_DCHECK(
- "DCHECK failed: fopen(file, \"r\") != nullptr."
- " : " +
- err,
- DPCHECK(fopen(file, "r") != nullptr));
+ EXPECT_DCHECK("DCHECK failed: fopen(file, \"r\") != nullptr. : " + err,
+ DPCHECK(fopen(file, "r") != nullptr));
- EXPECT_DCHECK(
- "DCHECK failed: fopen(file, \"r\") != nullptr."
- " foo: " +
- err,
- DPCHECK(fopen(file, "r") != nullptr) << "foo");
+ EXPECT_DCHECK("DCHECK failed: fopen(file, \"r\") != nullptr. foo: " + err,
+ DPCHECK(fopen(file, "r") != nullptr) << "foo");
}
TEST(CheckDeathTest, CheckOp) {
@@ -619,7 +607,7 @@
EXPECT_LOG_ERROR_WITH_FILENAME(base::Location::Current().file_name(),
base::Location::Current().line_number(),
NOTIMPLEMENTED() << "foo",
- expected_msg + "foo\n");
+ expected_msg + ". foo\n");
#else
// Expect nothing.
EXPECT_NO_LOG(NOTIMPLEMENTED() << "foo");
@@ -632,7 +620,7 @@
TEST(CheckTest, NotImplementedLogOnce) {
static const std::string expected_msg =
- kNotImplementedMessage + "void (anonymous namespace)::NiLogOnce()\n";
+ kNotImplementedMessage + "void (anonymous namespace)::NiLogOnce(). \n";
#if DCHECK_IS_ON()
EXPECT_LOG_ERROR_WITH_FILENAME(base::Location::Current().file_name(),
@@ -654,16 +642,17 @@
TEST(CheckTest, NotImplementedLogOnceWithStreamedParams) {
static const std::string expected_msg1 =
kNotImplementedMessage +
- "void (anonymous namespace)::NiLogTenTimesWithStream() iteration: 0\n";
+ "void (anonymous namespace)::NiLogTenTimesWithStream(). "
+ " iteration: 0\n";
#if DCHECK_IS_ON()
// Expect LOG(ERROR) with streamed params intact, exactly once.
EXPECT_LOG_ERROR_WITH_FILENAME(base::Location::Current().file_name(),
- base::Location::Current().line_number() - 13,
+ base::Location::Current().line_number() - 14,
NiLogTenTimesWithStream(), expected_msg1);
// A different NOTIMPLEMENTED_LOG_ONCE() call is still logged.
static const std::string expected_msg2 =
- kNotImplementedMessage + __PRETTY_FUNCTION__ + "tree fish\n";
+ kNotImplementedMessage + __PRETTY_FUNCTION__ + ". tree fish\n";
EXPECT_LOG_ERROR_WITH_FILENAME(base::Location::Current().file_name(),
base::Location::Current().line_number(),
NOTIMPLEMENTED_LOG_ONCE() << "tree fish",