-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Wip: fuzz: init manager #8714
Wip: fuzz: init manager #8714
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
syntax = "proto3"; | ||
|
||
package test.common.init; | ||
|
||
// Structured input for init_fuzz_test. | ||
|
||
enum InitEntityAction { | ||
|
||
// manager | ||
INIT_MANAGER_CREATION = 0; | ||
INIT_MANAGER_INITIALIZE = 1; | ||
INIT_MANAGER_DESTRUCTION = 2; | ||
|
||
// target | ||
INIT_TARGET_READY = 3; | ||
INIT_TARGET_DESTRUCTION = 4; | ||
|
||
// watcher | ||
INIT_WATCHER_DESTRUCTION = 5; | ||
|
||
// add | ||
INIT_MANAGER_ADD_TARGET = 6; | ||
} | ||
|
||
message InitAction { | ||
InitEntityAction action = 1; | ||
int32 param = 2; | ||
} | ||
|
||
message InitTestCase { | ||
repeated InitAction actions = 1; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
#include "common/common/assert.h" | ||
#include "common/init/manager_impl.h" | ||
#include "common/init/target_impl.h" | ||
#include "common/init/watcher_impl.h" | ||
|
||
#include "test/common/init/init_fuzz.pb.h" | ||
#include "test/fuzz/fuzz_runner.h" | ||
|
||
#include "absl/strings/str_cat.h" | ||
#include "gtest/gtest.h" | ||
|
||
namespace Envoy { | ||
namespace Fuzz { | ||
namespace { | ||
using namespace Init; | ||
|
||
class InitDriver { | ||
public: | ||
InitDriver(int manager_size, int target_size) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prefer fixed size types in Envoy code style, unsigned where it makes sense like here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. will do |
||
for (int i = 0; i < manager_size; i++) { | ||
ms_.emplace_back(std::make_unique<ManagerImpl>(absl::StrCat("fuzz_manager_", i))); | ||
ws_.emplace_back(std::make_unique<WatcherImpl>( | ||
absl::StrCat("fuzz_watcher_", i), [this, i]() mutable { ready_flags_[i] = true; })); | ||
ready_flags_.emplace_back(false); | ||
} | ||
for (int i = 0; i < target_size; i++) { | ||
ts_.emplace_back(std::make_unique<TargetImpl>(absl::StrCat("fuzz_target_", i), []() {})); | ||
} | ||
} | ||
|
||
void transit(const test::common::init::InitAction& action) { | ||
auto param = action.param(); | ||
int mid = (param % 1); | ||
int tid = (param % 1); | ||
switch (action.action()) { | ||
case test::common::init::INIT_MANAGER_INITIALIZE: | ||
ms_[mid]->initialize(*ws_[mid]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you provide an explanation of what you are aiming to verify by fuzzing? I'm guessing it's not crash resilience, so it's some correctness property. Is the range of possible inputs so large that we can't just use some unit tests or brute force testing? Etc. |
||
break; | ||
case test::common::init::INIT_MANAGER_ADD_TARGET: | ||
|
||
ms_[mid]->add(*ts_[tid]); | ||
break; | ||
case test::common::init::INIT_TARGET_READY: | ||
|
||
ts_[tid]->ready(); | ||
default: | ||
// NOT_IMPLEMENT_YET | ||
break; | ||
} | ||
}; | ||
|
||
std::vector<bool> ready_flags_; | ||
std::vector<std::unique_ptr<ManagerImpl>> ms_; | ||
std::vector<std::unique_ptr<TargetImpl>> ts_; | ||
std::vector<std::unique_ptr<WatcherImpl>> ws_; | ||
}; | ||
|
||
DEFINE_PROTO_FUZZER(const test::common::init::InitTestCase& input) { | ||
if (input.actions_size() < 3) { | ||
return; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Eventually it would be: |
||
} | ||
InitDriver driver(1, 1); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this parameterized when it's only used with a fixed size? |
||
ENVOY_LOG_MISC(critical, "input size {}", input.actions_size()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please make all log messages <= debug, since any emitted logs will slow down fuzzing. The fuzzer will emit critical in ClusterFuzz. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure. Will remove when it's ready to review |
||
for (const auto& act : input.actions()) { | ||
driver.transit(act); | ||
} | ||
RELEASE_ASSERT(driver.ready_flags_[0], "manager not initialized"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How do you know this will be non-empty? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The driver should be initialized with reasonable number of manager. |
||
} | ||
} // namespace | ||
} // namespace Fuzz | ||
} // namespace Envoy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@asraa do you think we should advocate for FuzzDataProvider here (for performance, and because the trace format is simple), or are there good reasons to keep this a proto trace format?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FuzzDataProvider
! TIL. Will explore and introduceThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a downside; it's harder to hand-craft corpuses (and understand failing corpus files). It would be ideal if there was some CLI tool that translated from a proto representation of the binary data to the raw binary for
FuzzDataProvider
, so that both of these can be better handled. Not sure if anyone has built this kind of thing already.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh no!! I had suggested this change yesterday but I didn't know GH review process has an extra submit button.
Yeah, I personally think that if the actions are simple enough to describe, using a
FuzzedDataProvider
to chose oneof some number of actions is better.But if there's a strong case for the order of the scenarios bringing interesting behavior (the ordering of ready, add target, destruction) without necessarily strictly increasing code coverage, I think the proto trace format is better. I only think though that if you decide to do the proto trace format way, that you enter a good number of corpus entries.