diff --git a/compilation/types/slither.go b/compilation/types/slither.go index 4dc159a2..d55c044b 100644 --- a/compilation/types/slither.go +++ b/compilation/types/slither.go @@ -4,9 +4,9 @@ import ( "encoding/json" "fmt" "github.com/crytic/medusa/logging" - "github.com/crytic/medusa/logging/colors" "os" "os/exec" + "time" ) // SlitherConfig determines whether to run slither and whether and where to cache the results from slither @@ -58,7 +58,7 @@ func (s *SlitherConfig) Run(target string) (*SlitherResults, error) { // Check to see if the file exists in the first place. // If not, we will re-run slither if _, err = os.Stat(s.CachePath); os.IsNotExist(err) { - logging.GlobalLogger.Info("No slither cache file found at ", colors.Bold, s.CachePath) + logging.GlobalLogger.Info("No Slither cached results found at ", s.CachePath) haveCachedResults = false } else { // We found the cached file @@ -66,12 +66,21 @@ func (s *SlitherConfig) Run(target string) (*SlitherResults, error) { return nil, err } haveCachedResults = true + logging.GlobalLogger.Info("Using cached Slither results found at ", s.CachePath) } } // Run slither if we do not have cached results, or we cannot find the cached results if !haveCachedResults { - out, err = exec.Command("slither", target, "--ignore-compile", "--print", "echidna", "--json", "-").CombinedOutput() + // Log the command + cmd := exec.Command("slither", target, "--ignore-compile", "--print", "echidna", "--json", "-") + logging.GlobalLogger.Info("Running Slither:\n", cmd.String()) + + // Run slither + start := time.Now() + out, err = cmd.CombinedOutput() + logging.GlobalLogger.Info("Finished running Slither in ", time.Since(start).Round(time.Second)) + if err != nil { return nil, err } diff --git a/fuzzing/fuzzer.go b/fuzzing/fuzzer.go index 5e691f5a..d384cf89 100644 --- a/fuzzing/fuzzer.go +++ b/fuzzing/fuzzer.go @@ -301,7 +301,7 @@ func (f *Fuzzer) AddCompilationTargets(compilations []compilationTypes.Compilati slitherResults, err := f.config.Slither.Run(target) if err != nil || slitherResults == nil { if err != nil { - // TODO: Log error + f.logger.Warn("Failed to run slither", err) } seedFromAST = true } diff --git a/fuzzing/fuzzer_test.go b/fuzzing/fuzzer_test.go index 5a6aeb1c..87edf15e 100644 --- a/fuzzing/fuzzer_test.go +++ b/fuzzing/fuzzer_test.go @@ -64,15 +64,46 @@ func TestFuzzerHooks(t *testing.T) { // TestSlitherPrinter runs slither and ensures that the constants are correctly added to the value set func TestSlitherPrinter(t *testing.T) { - // Run a test to simulate out of gas errors to make sure its handled well by the Chain and does not panic. + expectedInts := []int64{ + 123, // value of `x` + 12, // constant in testFuzz + 135, // sum of 123 + 12 + 456, // value of `y` + -123, // negative of 123 + -12, // negative of 12 + -135, // negative of 135 + -456, // negative of 456 + 0, // the false in testFuzz is added as zero in the value set + 1, // true is evaluated as 1 + -1, // negative of 1 + } + expectedAddrs := []common.Address{ + common.HexToAddress("0"), + } + expectedStrings := []string{ + "Hello World!", + } + // We actually don't need to start the fuzzer and only care about the instantiation of the fuzzer runFuzzerTest(t, &fuzzerSolcFileTest{ filePath: "testdata/contracts/slither/slither.sol", configUpdates: func(config *config.ProjectConfig) { config.Fuzzing.TargetContracts = []string{"TestContract"} - config.Fuzzing.Workers = 1 }, method: func(f *fuzzerTestContext) { - t.Log(f.fuzzer.slitherResults) + // Look through the value set to make sure all the ints, addrs, and strings are in there + + // Check for ints + for _, x := range expectedInts { + assert.True(t, f.fuzzer.baseValueSet.ContainsInteger(new(big.Int).SetInt64(x))) + } + // Check for addresses + for _, addr := range expectedAddrs { + assert.True(t, f.fuzzer.baseValueSet.ContainsAddress(addr)) + } + // Check for strings + for _, str := range expectedStrings { + assert.True(t, f.fuzzer.baseValueSet.ContainsString(str)) + } }, }) } diff --git a/fuzzing/testdata/contracts/slither/slither.sol b/fuzzing/testdata/contracts/slither/slither.sol index 363e619c..cf50bedc 100644 --- a/fuzzing/testdata/contracts/slither/slither.sol +++ b/fuzzing/testdata/contracts/slither/slither.sol @@ -1,11 +1,18 @@ +// This test ensures that all the constants in this contract are added to the value set contract TestContract { + // Uint constant + uint256 constant x = 123 + 12; + constructor() {} function testFuzz(uint256 z) public { - uint256 x = 123; - int256 y = 5 * 72; + // Set z to x so that 123, 12, and (123 + 12 = 135) are captured as constants + z = x; + // Add a bunch of other constants + int256 y = 456; address addr = address(0); - string memory str = "hello world"; + bool b = true; + string memory str = "Hello World!"; assert(false); } } \ No newline at end of file diff --git a/fuzzing/valuegeneration/value_set_from_slither.go b/fuzzing/valuegeneration/value_set_from_slither.go index 615459cb..827e1607 100644 --- a/fuzzing/valuegeneration/value_set_from_slither.go +++ b/fuzzing/valuegeneration/value_set_from_slither.go @@ -36,6 +36,5 @@ func (vs *ValueSet) SeedFromSlither(slither *compilationTypes.SlitherResults) { vs.AddAddress(common.BigToAddress(addressBigInt)) vs.AddBytes([]byte(constant.Value)) } - } }