[fuzz] Improve fuzz job tree walking
This CL reworks Fuzzer::Check and its related methods to look for
component manifests when run on a Fuchisa package. It also reformats
the output to make the salient details easier to spot.
SEC-103
Tests: Reran unit tests, manually tested with other packages
Change-Id: I5060d013e068ae24a6aaaa9c4c5e63a4635fe10b
diff --git a/system/ulib/fuzz-utils/fuzzer.cpp b/system/ulib/fuzz-utils/fuzzer.cpp
index 66424d2..8ba845c 100644
--- a/system/ulib/fuzz-utils/fuzzer.cpp
+++ b/system/ulib/fuzz-utils/fuzzer.cpp
@@ -92,7 +92,7 @@
void Fuzzer::Reset() {
cmd_ = kNone;
name_.clear();
- executable_.clear();
+ target_.clear();
root_.clear();
resource_path_.Reset();
data_path_.Reset();
@@ -326,10 +326,10 @@
void Fuzzer::GetArgs(StringList* out) {
out->clear();
- if (strstr(executable_.c_str(), "fuchsia-pkg://fuchsia.com/") == executable_.c_str()) {
+ if (strstr(target_.c_str(), "fuchsia-pkg://fuchsia.com/") == target_.c_str()) {
out->push_back("/system/bin/run");
}
- out->push_back(executable_.c_str());
+ out->push_back(target_.c_str());
const char* key;
const char* val;
options_.begin();
@@ -409,20 +409,27 @@
bool Fuzzer::CheckProcess(zx_handle_t process) const {
char name[ZX_MAX_NAME_LEN];
zx_info_process_t info;
- if (zx_object_get_property(process, ZX_PROP_NAME, name, sizeof(name)) != ZX_OK ||
- strcmp(name, executable_.c_str()) != 0 ||
- zx_object_get_info(process, ZX_INFO_PROCESS, &info, sizeof(info), nullptr, nullptr) !=
- ZX_OK) {
+
+ if (zx_object_get_property(process, ZX_PROP_NAME, name, sizeof(name)) != ZX_OK) {
+ return false;
+ }
+
+ const char* target = target_.c_str();
+ const char* meta = strstr(target, "#meta/");
+ if (meta) {
+ target = meta + strlen("#meta/");
+ }
+ if (strcmp(name, target) != 0 || zx_object_get_info(process, ZX_INFO_PROCESS, &info,
+ sizeof(info), nullptr, nullptr) != ZX_OK) {
return false;
}
if (!info.started) {
- fprintf(out_, "Fuzzer '%s' has not started.\n", name_.c_str());
+ fprintf(out_, "%s: NOT STARTED\n", name_.c_str());
} else if (!info.exited) {
- fprintf(out_, "Fuzzer '%s' is running.\n", name_.c_str());
+ fprintf(out_, "%s: RUNNING\n", name_.c_str());
} else {
- fprintf(out_, "Fuzzer '%s' exited with return code %" PRId64 ".\n", name_.c_str(),
- info.return_code);
+ fprintf(out_, "%s: EXITED (return code = %" PRId64 ")\n", name_.c_str(), info.return_code);
}
return true;
@@ -494,7 +501,7 @@
fuzzers.begin();
fuzzers.next(&name, &executable);
name_.Set(name);
- executable_.Set(executable);
+ target_.Set(executable);
fbl::String package, target;
if ((rc = ParseName(name_.c_str(), &package, &target)) != ZX_OK) {
@@ -649,16 +656,16 @@
// Report fuzzer execution status
Walker walker(this);
if (walker.WalkRootJobTree() != ZX_ERR_STOP) {
- fprintf(out_, "Fuzzer '%s' is not running.\n", name_.c_str());
+ fprintf(out_, "%s: STOPPED\n", name_.c_str());
}
// Fuzzer details
- fprintf(out_, "The fuzzer binary is located at: %s\n", executable_.c_str());
- fprintf(out_, "The fuzzing data is located at: %s\n", data_path_.c_str());
+ fprintf(out_, " Target info: %s\n", target_.c_str());
+ fprintf(out_, " Output path: %s\n", data_path_.c_str());
// Report corpus details, if present
if ((rc = data_path_.Push("corpus")) != ZX_OK) {
- fprintf(out_, "No fuzzing corpus was found\n");
+ fprintf(out_, " Corpus size: 0 inputs / 0 bytes\n");
} else {
auto corpus = data_path_.List();
size_t corpus_size = 0;
@@ -669,8 +676,7 @@
}
corpus_size += input_size;
}
- fprintf(out_, "The fuzzing corpus has %zu inputs totaling %zu bytes.\n", corpus->length(),
- corpus_size);
+ fprintf(out_, " Corpus size: %zu inputs / %zu bytes\n", corpus->length(), corpus_size);
data_path_.Pop();
}
@@ -681,11 +687,12 @@
artifacts->keep_if_any(&prefixes);
size_t num_artifacts = artifacts->length();
if (num_artifacts == 0) {
- fprintf(out_, "The fuzzer has not produced any artifacts.\n");
+ fprintf(out_, " Artifacts: None\n");
} else {
- fprintf(out_, "The fuzzer has produced %zu artifacts:\n", num_artifacts);
- for (const char* artifact = artifacts->first(); artifact; artifact = artifacts->next()) {
- fprintf(out_, " %s\n", artifact);
+ const char* artifact = artifacts->first();
+ fprintf(out_, " Artifacts: %s\n", artifact);
+ while ((artifact = artifacts->next())) {
+ fprintf(out_, " %s\n", artifact);
}
}
diff --git a/system/ulib/fuzz-utils/include/fuzz-utils/fuzzer.h b/system/ulib/fuzz-utils/include/fuzz-utils/fuzzer.h
index 4fd21b5..cfed862 100644
--- a/system/ulib/fuzz-utils/include/fuzz-utils/fuzzer.h
+++ b/system/ulib/fuzz-utils/include/fuzz-utils/fuzzer.h
@@ -46,7 +46,7 @@
void set_root(const char* root) { root_.Set(root); }
void set_out(FILE* out) { out_ = out; }
void set_err(FILE* err) { err_ = err; }
- void set_executable(const char* executable) { executable_.Set(executable); }
+ void set_target(const char* target) { target_.Set(target); }
// Interpret the given |args| and execute the appropriate subcommand.
zx_status_t Run(StringList* args);
@@ -120,7 +120,7 @@
// Fuzzer name; may be a user-supplied pattern until resolved into a package/target.
fbl::String name_;
// Path on target to the fuzzer binary
- fbl::String executable_;
+ fbl::String target_;
// Path that the resource and data paths are relative to; primarily used for testing.
fbl::String root_;
// Path on target to where immutable fuzzing resources are stored
diff --git a/system/utest/fuzz-utils/fuzzer.cpp b/system/utest/fuzz-utils/fuzzer.cpp
index 4773f03..399c43a 100644
--- a/system/utest/fuzz-utils/fuzzer.cpp
+++ b/system/utest/fuzz-utils/fuzzer.cpp
@@ -666,46 +666,46 @@
ASSERT_TRUE(test.Eval("check zircon/target1"));
EXPECT_EQ(ZX_OK, test.Run());
- EXPECT_TRUE(test.InStdOut("not running"));
+ EXPECT_TRUE(test.InStdOut("stopped"));
EXPECT_TRUE(test.InStdOut(test.executable()));
EXPECT_TRUE(test.InStdOut(test.data_path()));
- EXPECT_TRUE(test.InStdOut("no fuzzing corpus"));
- EXPECT_TRUE(test.InStdOut("has not produced any artifacts."));
+ EXPECT_TRUE(test.InStdOut("0 inputs"));
+ EXPECT_TRUE(test.InStdOut("none"));
ASSERT_TRUE(test.Eval("check zircon/target2"));
EXPECT_EQ(ZX_OK, test.Run());
- EXPECT_TRUE(test.InStdOut("not running"));
+ EXPECT_TRUE(test.InStdOut("stopped"));
EXPECT_TRUE(test.InStdOut(test.executable()));
EXPECT_TRUE(test.InStdOut(test.data_path()));
- EXPECT_TRUE(test.InStdOut("fuzzing corpus has"));
- EXPECT_TRUE(test.InStdOut("has produced"));
+ EXPECT_TRUE(test.InStdOut("0 inputs"));
+ EXPECT_TRUE(test.InStdOut("crash"));
// Fuchsia tests
ASSERT_TRUE(test.InitFuchsia());
ASSERT_TRUE(test.Eval("check zircon/target2"));
EXPECT_EQ(ZX_OK, test.Run());
- EXPECT_TRUE(test.InStdOut("not running"));
+ EXPECT_TRUE(test.InStdOut("stopped"));
EXPECT_TRUE(test.InStdOut(test.executable()));
EXPECT_TRUE(test.InStdOut(test.data_path()));
- EXPECT_TRUE(test.InStdOut("fuzzing corpus has"));
- EXPECT_TRUE(test.InStdOut("has produced"));
+ EXPECT_TRUE(test.InStdOut("0 inputs"));
+ EXPECT_TRUE(test.InStdOut("crash"));
ASSERT_TRUE(test.Eval("check fuchsia/target1"));
EXPECT_EQ(ZX_OK, test.Run());
- EXPECT_TRUE(test.InStdOut("not running"));
+ EXPECT_TRUE(test.InStdOut("stopped"));
EXPECT_TRUE(test.InStdOut(test.executable()));
EXPECT_TRUE(test.InStdOut(test.data_path()));
- EXPECT_TRUE(test.InStdOut("no fuzzing corpus"));
- EXPECT_TRUE(test.InStdOut("has not produced any artifacts."));
+ EXPECT_TRUE(test.InStdOut("0 inputs"));
+ EXPECT_TRUE(test.InStdOut("none"));
ASSERT_TRUE(test.Eval("check fuchsia/target4"));
EXPECT_EQ(ZX_OK, test.Run());
- EXPECT_TRUE(test.InStdOut("not running"));
+ EXPECT_TRUE(test.InStdOut("stopped"));
EXPECT_TRUE(test.InStdOut(test.executable()));
EXPECT_TRUE(test.InStdOut(test.data_path()));
- EXPECT_TRUE(test.InStdOut("fuzzing corpus has"));
- EXPECT_TRUE(test.InStdOut("has produced"));
+ EXPECT_TRUE(test.InStdOut("0 inputs"));
+ EXPECT_TRUE(test.InStdOut("crash"));
END_TEST;
}
diff --git a/system/utest/fuzz-utils/test-fuzzer.cpp b/system/utest/fuzz-utils/test-fuzzer.cpp
index 4db45b1..0561cc0 100644
--- a/system/utest/fuzz-utils/test-fuzzer.cpp
+++ b/system/utest/fuzz-utils/test-fuzzer.cpp
@@ -121,9 +121,9 @@
return -1;
}
-bool TestFuzzer::CheckProcess(zx_handle_t process, const char* executable) {
- if (executable) {
- set_executable(executable);
+bool TestFuzzer::CheckProcess(zx_handle_t process, const char* target) {
+ if (target) {
+ set_target(target);
}
return Fuzzer::CheckProcess(process);
}