Skip to content

Commit

Permalink
bazel: extend oss-fuzz set up
Browse files Browse the repository at this point in the history
Split between CFLAGS and CXXFLAGS. This is needed to make tensorflow
work.

Related: google/oss-fuzz#8992

Signed-off-by: David Korczynski <david@adalogics.com>
  • Loading branch information
DavidKorczynski committed Nov 16, 2022
1 parent de98ad9 commit 38e563d
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 15 deletions.
26 changes: 23 additions & 3 deletions doc/domains-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ failure.
IMPORTANT: Note that *optional* fields are not always set by the fuzzer.

**Making an optional field always or never set:** If you want to make sure an
optional field is always set, you can use `With<Type>FieldAlswaysSet()`.
optional field is always set, you can use `With<Type>FieldAlwaysSet()`.
Similarly, if you want an optional field to be always left unset, you can use
`With<Type>FieldUnset()`. For example:

Expand All @@ -301,7 +301,7 @@ FUZZ_TEST(MySuite, DoingStuffDoesNotCrashWithCustomProto).
```
**Setting the domain of non-optional fields:** For *required* fields, use
`With<Type>FieldAlswaysSet` and for *repeated* fields use
`With<Type>FieldAlwaysSet` and for *repeated* fields use
`WithRepeated<Type>Field`:
```c++
Expand Down Expand Up @@ -365,7 +365,7 @@ FUZZ_TEST(MySuite, DoingStuffDoesNotCrashWithCustomProto)
// All int fields should be positive
.WithInt32Fields(Positive<int>())
// except balance field which can be negative
.WihtInt32Field("balance", Arbitrary<int>())
.WithInt32Field("balance", Arbitrary<int>())
// and except all zipcode fields which should have 5 digits
.WithInt32Fields(IsZipcode, InRange(10000, 99999))
// All Timestamp fields should have "nanos" field unset.
Expand Down Expand Up @@ -760,6 +760,26 @@ auto AnyDurationString() {
}
```

### FlatMap-ing Domains

Sometimes, it is necessary to use the output of one domain as the input for
another domain. This can be accomplished with the `FlatMap()` function, which
is like `Map()`, but it takes a function which returns a `Domain`. For
example:

```c++
auto AnyVectorOfFixedLengthStrings(int size) {
return VectorOf(Arbitrary<std::string>().WithSize(size));
}
auto AnyVectorOfEqualSizedStrings() {
return FlatMap(AnyVectorOfFixedLengthStrings, /*size=*/ InRange(0, 10));
}
```
If `AnyVectorOfFixedLengthStrings()` had been passed to `Map()`, it would have
generated a `Domain<Domain<std::string>>`. `FlatMap()` "flattens" this to a
`Domain<std::string>`.
### Filter-ing Domains
The `Filter` domain takes a domain and a predicate and returns a new domain that
Expand Down
19 changes: 15 additions & 4 deletions e2e_tests/functional_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "absl/strings/substitute.h"
#include "absl/time/time.h"
Expand Down Expand Up @@ -97,7 +98,7 @@ class TempDir {
};

RunResults RunBinaryWith(
std::string_view binary, std::string_view flag,
std::string_view binary, std::string_view flags,
const absl::flat_hash_map<std::string, std::string>& env = {},
absl::Duration timeout = absl::InfiniteDuration()) {
// We need to unset these env vars to prevent the testing infrastructure from
Expand All @@ -115,14 +116,18 @@ RunResults RunBinaryWith(
unsetenv("TEST_TOTAL_SHARDS");
unsetenv("TEST_SHARD_INDEX");

return RunCommand({std::string(binary), std::string(flag)}, env, timeout);
std::vector<std::string> args = {std::string(binary)};
std::vector<std::string> split_flags = absl::StrSplit(flags, ' ');
args.insert(args.end(), split_flags.begin(), split_flags.end());

return RunCommand(args, env, timeout);
}

RunResults RunWith(
std::string_view flag,
std::string_view flags,
const absl::flat_hash_map<std::string, std::string>& env = {},
absl::Duration timeout = absl::InfiniteDuration()) {
return RunBinaryWith(BinaryPath(), flag, env, timeout);
return RunBinaryWith(BinaryPath(), flags, env, timeout);
}

// The following tests are on "unit testing mode" functionality, and can run
Expand Down Expand Up @@ -701,6 +706,12 @@ TEST_F(FuzzingModeTest, LimitsFuzzingRunsWhenEnvVarIsSet) {
<< std_err;
}

TEST_F(FuzzingModeTest, LimitsFuzzingRunsWhenTimeoutIsSet) {
auto [status, std_out, std_err] = RunWith(
"--fuzz=MySuite.PassesWithPositiveInput --fuzz_for=1s");
EXPECT_THAT(std_err, HasSubstr("Fuzzing timeout set to: 1s")) << std_err;
}

TEST_F(FuzzingModeTest, ReproducerIsDumpedWhenEnvVarIsSet) {
TempDir out_dir;

Expand Down
1 change: 1 addition & 0 deletions fuzztest/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ cc_library(
":runtime",
"@com_google_absl//absl/flags:flag",
"@com_google_absl//absl/flags:parse",
"@com_google_absl//absl/time",
"@com_google_googletest//:gtest",
],
)
Expand Down
31 changes: 23 additions & 8 deletions fuzztest/fuzztest_gtest_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "gtest/gtest.h"
#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "absl/time/time.h"
#include "./fuzztest/fuzztest.h"
#include "./fuzztest/googletest_adaptor.h"
#include "./fuzztest/internal/runtime.h"
Expand All @@ -33,6 +34,11 @@ ABSL_FLAG(std::string, fuzz, "",
"also possible to provide part of the name, e.g., `--fuzz=MyProp`, "
"if it matches a single fuzz test.");

ABSL_FLAG(absl::Duration, fuzz_for, absl::InfiniteDuration(),
"Runs all fuzz tests in fuzzing mode for the specified duration. Can "
"be combined with --fuzz to select a single fuzz tests, or "
"with --gtest_filter to select a subset of fuzz tests.");

int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);

Expand All @@ -45,18 +51,27 @@ int main(int argc, char** argv) {
return 0;
}

auto fuzz = absl::GetFlag(FLAGS_fuzz);
if (fuzz.empty()) {
// Run all tests in the unit test mode.
GOOGLEFUZZTEST_REGISTER_FOR_GOOGLETEST(fuzztest::RunMode::kUnitTest, &argc,
&argv);
} else {
const auto fuzz = absl::GetFlag(FLAGS_fuzz);
const bool is_fuzz_specified = !fuzz.empty();

if (is_fuzz_specified) {
// Select a specific test to be run in the in fuzzing mode.
const std::string matching_fuzz_test =
fuzztest::GetMatchingFuzzTestOrExit(fuzz);
const auto matching_fuzz_test = fuzztest::GetMatchingFuzzTestOrExit(fuzz);
GTEST_FLAG_SET(filter, matching_fuzz_test);
}

const auto duration = absl::GetFlag(FLAGS_fuzz_for);
const bool is_duration_specified =
absl::ZeroDuration() < duration && duration < absl::InfiniteDuration();
if (is_duration_specified) {
fuzztest::internal::fuzz_time_limit = duration;
}
if (is_fuzz_specified || is_duration_specified) {
GOOGLEFUZZTEST_REGISTER_FOR_GOOGLETEST(fuzztest::RunMode::kFuzz, &argc,
&argv);
} else {
GOOGLEFUZZTEST_REGISTER_FOR_GOOGLETEST(fuzztest::RunMode::kUnitTest, &argc,
&argv);
}
return RUN_ALL_TESTS();
}
1 change: 1 addition & 0 deletions fuzztest/internal/runtime.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
namespace fuzztest::internal {

RunMode run_mode = RunMode::kUnitTest;
ABSL_CONST_INIT absl::Duration fuzz_time_limit = absl::InfiniteDuration();
std::atomic<bool> external_failure_was_detected;
std::atomic<bool> termination_requested;
OnFailure on_failure;
Expand Down
10 changes: 10 additions & 0 deletions fuzztest/internal/runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ extern std::atomic<bool> external_failure_was_detected;
extern std::atomic<bool> termination_requested;

extern RunMode run_mode;
extern absl::Duration fuzz_time_limit;

class OnFailure {
public:
Expand Down Expand Up @@ -393,6 +394,12 @@ class FuzzTestFuzzerImpl<
}
}

if (fuzz_time_limit != absl::InfiniteDuration()) {
absl::FPrintF(GetStderr(), "[.] Fuzzing timeout set to: %s\n",
absl::FormatDuration(fuzz_time_limit));
time_limit_ = stats_.start_time + fuzz_time_limit;
}

// Fuzz corpus elements in round robin fashion.
while (!ShouldStop()) {
Input input_to_mutate = [&]() -> Input {
Expand Down Expand Up @@ -750,6 +757,8 @@ class FuzzTestFuzzerImpl<

bool ShouldStop() {
if (runs_limit_.has_value() && stats_.runs >= *runs_limit_) return true;
if (time_limit_ != absl::InfiniteFuture() && absl::Now() > time_limit_)
return true;
return termination_requested.load(std::memory_order_relaxed);
}

Expand All @@ -774,6 +783,7 @@ class FuzzTestFuzzerImpl<
std::string_view corpus_out_dir_;
RuntimeStats stats_{};
std::optional<size_t> runs_limit_;
absl::Time time_limit_ = absl::InfiniteFuture();

#ifdef FUZZTEST_COMPATIBILITY_MODE
friend class FuzzTestExternalEngineAdaptor<RegBase, Fixture, TargetFunction>;
Expand Down

0 comments on commit 38e563d

Please sign in to comment.