Commit 4ad08c82 authored by Michael Achenbach's avatar Michael Achenbach Committed by Commit Bot

Enable simulating errors to test fuzzer reliability

This adds a d8 flag --simulate-errors, which on shutdown will cause
certain errors. This enables testing the reliability of sanitizers.

This will cause a fatal error, a dcheck (if available) or a
violation that can be detected with one of the following sanitizers:
ASAN, UBSAN, MSAN, CFI.

The same flag used in differential fuzzing will cause an error
subsumed with the error state "fake_difference".

Bug: chromium:1152412
Change-Id: I4b36c6fe716797004d634263617d22ca67b05600
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2554999
Commit-Queue: Michael Achenbach <machenbach@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71430}
parent 28f0b62a
...@@ -2645,6 +2645,54 @@ void Shell::OnExit(v8::Isolate* isolate) { ...@@ -2645,6 +2645,54 @@ void Shell::OnExit(v8::Isolate* isolate) {
delete counters_file_; delete counters_file_;
delete counter_map_; delete counter_map_;
if (options.simulate_errors) {
// Simulate several errors detectable by fuzzers behind a flag.
SimulateErrors();
}
}
void Dummy(char* arg) {}
void Shell::SimulateErrors() {
// Initialize a fresh RNG to not interfere with JS execution.
std::unique_ptr<base::RandomNumberGenerator> rng;
int64_t seed = internal::FLAG_random_seed;
if (seed != 0) {
rng = std::make_unique<base::RandomNumberGenerator>(seed);
} else {
rng = std::make_unique<base::RandomNumberGenerator>();
}
double p = rng->NextDouble();
if (p < 0.1) {
// Caught in all build types.
FATAL("Fake error.");
} else if (p < 0.2) {
// Caught in debug builds.
DCHECK(false);
} else if (p < 0.3) {
// Caught by UBSAN.
int32_t val = -1;
USE(val << 8);
} else if (p < 0.4) {
// Use-after-free caught by ASAN.
std::vector<bool>* storage = new std::vector<bool>(3);
delete storage;
USE(storage->at(1));
} else if (p < 0.5) {
// Use-of-uninitialized-value caught by MSAN.
int uninitialized[1];
if (uninitialized[0])
USE(uninitialized);
} else if (p < 0.6) {
// Control flow violation caught by CFI.
void (*func)() = (void (*)()) & Dummy;
func();
} else if (p < 0.7) {
// Observable difference caught by differential fuzzing.
printf("___fake_difference___\n");
}
} }
static FILE* FOpen(const char* path, const char* mode) { static FILE* FOpen(const char* path, const char* mode) {
...@@ -3392,6 +3440,9 @@ bool Shell::SetOptions(int argc, char* argv[]) { ...@@ -3392,6 +3440,9 @@ bool Shell::SetOptions(int argc, char* argv[]) {
} else if (strcmp(argv[i], "--no-arguments") == 0) { } else if (strcmp(argv[i], "--no-arguments") == 0) {
options.include_arguments = false; options.include_arguments = false;
argv[i] = nullptr; argv[i] = nullptr;
} else if (strcmp(argv[i], "--simulate-errors") == 0) {
options.simulate_errors = true;
argv[i] = nullptr;
} else if (strcmp(argv[i], "--stress-opt") == 0) { } else if (strcmp(argv[i], "--stress-opt") == 0) {
options.stress_opt = true; options.stress_opt = true;
argv[i] = nullptr; argv[i] = nullptr;
......
...@@ -343,6 +343,7 @@ class ShellOptions { ...@@ -343,6 +343,7 @@ class ShellOptions {
DisallowReassignment<bool> omit_quit = {"omit-quit", false}; DisallowReassignment<bool> omit_quit = {"omit-quit", false};
DisallowReassignment<bool> wait_for_background_tasks = { DisallowReassignment<bool> wait_for_background_tasks = {
"wait-for-background-tasks", true}; "wait-for-background-tasks", true};
DisallowReassignment<bool> simulate_errors = {"simulate-errors", false};
DisallowReassignment<bool> stress_opt = {"stress-opt", false}; DisallowReassignment<bool> stress_opt = {"stress-opt", false};
DisallowReassignment<int> stress_runs = {"stress-runs", 1}; DisallowReassignment<int> stress_runs = {"stress-runs", 1};
DisallowReassignment<bool> stress_snapshot = {"stress-snapshot", false}; DisallowReassignment<bool> stress_snapshot = {"stress-snapshot", false};
...@@ -622,6 +623,7 @@ class Shell : public i::AllStatic { ...@@ -622,6 +623,7 @@ class Shell : public i::AllStatic {
Local<Value> name); Local<Value> name);
static void StoreInCodeCache(Isolate* isolate, Local<Value> name, static void StoreInCodeCache(Isolate* isolate, Local<Value> name,
const ScriptCompiler::CachedData* data); const ScriptCompiler::CachedData* data);
static void SimulateErrors();
// We may have multiple isolates running concurrently, so the access to // We may have multiple isolates running concurrently, so the access to
// the isolate_status_ needs to be concurrency-safe. // the isolate_status_ needs to be concurrency-safe.
static base::LazyMutex isolate_status_lock_; static base::LazyMutex isolate_status_lock_;
......
...@@ -57,6 +57,8 @@ IGNORE_TEST_CASES = { ...@@ -57,6 +57,8 @@ IGNORE_TEST_CASES = {
IGNORE_OUTPUT = { IGNORE_OUTPUT = {
'crbug.com/689877': 'crbug.com/689877':
re.compile(r'^.*SyntaxError: .*Stack overflow$', re.M), re.compile(r'^.*SyntaxError: .*Stack overflow$', re.M),
'fake_difference':
re.compile(r'^.*___fake_difference___$', re.M),
} }
# Lines matching any of the following regular expressions will be ignored # Lines matching any of the following regular expressions will be ignored
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment