Skip to content

Commit

Permalink
Custom logger for unstructured and structured logging (#171)
Browse files Browse the repository at this point in the history
This PR introduces colorized logging for console and future support for structured logging
---------

Co-authored-by: David Pokora <dpokora@gmail.com>
  • Loading branch information
anishnaik and Xenomega authored Jul 14, 2023
1 parent baa414b commit 4c5c993
Show file tree
Hide file tree
Showing 34 changed files with 1,122 additions and 258 deletions.
6 changes: 4 additions & 2 deletions chain/cheat_code_contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package chain

import (
"encoding/binary"
"fmt"
"github.com/crytic/medusa/logging"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
Expand Down Expand Up @@ -100,12 +102,12 @@ func (c *CheatCodeContract) Abi() *abi.ABI {
func (c *CheatCodeContract) addMethod(name string, inputs abi.Arguments, outputs abi.Arguments, handler cheatCodeMethodHandler) {
// Verify a method name was provided
if name == "" {
panic("could not add method to precompiled cheatcode contract, empty method name provided")
logging.GlobalLogger.Panic("Failed to add method to precompile cheatcode contract", fmt.Errorf("empty method name provided"))
}

// Verify a method handler was provided
if handler == nil {
panic("could not add method to precompiled cheatcode contract, nil method handler provided")
logging.GlobalLogger.Panic("Failed to add method to precompile cheatcode contract", fmt.Errorf("nil method handler provided"))
}

// Set the method information in our method lookup
Expand Down
35 changes: 24 additions & 11 deletions cmd/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,13 @@ var supportedShells = []string{"bash", "zsh", "powershell"}

// completionCmd represents the completion command
var completionCmd = &cobra.Command{
Use: "completion <shell>",
Short: "generate the autocompletion script for medusa for the specific shell",
Long: generalComDesc,
Args: cmdValidateCompletionArgs,
RunE: cmdRunCompletion,
Use: "completion <shell>",
Short: "Generate the autocompletion script for medusa for the specific shell",
Long: generalComDesc,
Args: cmdValidateCompletionArgs,
RunE: cmdRunCompletion,
SilenceUsage: true,
SilenceErrors: true,
}

func init() {
Expand All @@ -62,12 +64,16 @@ func init() {
func cmdValidateCompletionArgs(cmd *cobra.Command, args []string) error {
// Make sure we have exactly 1 argument
if err := cobra.ExactArgs(1)(cmd, args); err != nil {
return fmt.Errorf("completion requires only 1 shell argument (options: %s)", strings.Join(supportedShells, ", "))
err = fmt.Errorf("completion requires only 1 shell argument (options: %s)", strings.Join(supportedShells, ", "))
cmdLogger.Error("Failed to validate args for completion command", err)
return err
}

// Make sure that the shell is a supported type
if contains := slices.Contains(supportedShells, args[0]); !contains {
return fmt.Errorf("%s is not a supported shell", args[0])
err := fmt.Errorf("%s is not a supported shell", args[0])
cmdLogger.Error("Failed to validate args for completion command", err)
return err
}

return nil
Expand All @@ -76,15 +82,22 @@ func cmdValidateCompletionArgs(cmd *cobra.Command, args []string) error {
// cmdRunCompletion executes the completion CLI command
func cmdRunCompletion(cmd *cobra.Command, args []string) error {
// NOTE: Please be aware that if the supported shells changes, then this switch statement must also change
var err error
switch args[0] {
case "bash":
return cmd.Root().GenBashCompletionV2(os.Stdout, true)
err = cmd.Root().GenBashCompletionV2(os.Stdout, true)
case "zsh":
return cmd.Root().GenZshCompletion(os.Stdout)
err = cmd.Root().GenZshCompletion(os.Stdout)
case "powershell":
return cmd.Root().GenPowerShellCompletionWithDesc(os.Stdout)
err = cmd.Root().GenPowerShellCompletionWithDesc(os.Stdout)
default:
// We are throwing a panic here because our validation function should have handled this and something is wrong.
panic(fmt.Errorf("%s is not a supported shell type", args[0]))
cmdLogger.Panic("Failed to run the completion command", fmt.Errorf("%s is not a supported shell type", args[0]))
}

// Log an error if we encountered one
if err != nil {
cmdLogger.Error("Failed to run the completion command", err)
}
return err
}
89 changes: 52 additions & 37 deletions cmd/fuzz.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cmd

import (
"fmt"
"github.com/crytic/medusa/logging/colors"
"os"
"os/signal"
"path/filepath"
Expand All @@ -14,53 +15,59 @@ import (

// fuzzCmd represents the command provider for fuzzing
var fuzzCmd = &cobra.Command{
Use: "fuzz",
Short: "Starts a fuzzing campaign",
Long: `Starts a fuzzing campaign`,
Args: cmdValidateFuzzArgs,
RunE: cmdRunFuzz,
// Run dynamic completion of nouns
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
// Gather a list of flags that are available to be used in the current command but have not been used yet
var unusedFlags []string

// Examine all the flags, and add any flags that have not been set in the current command line
// to a list of unused flags
cmd.Flags().VisitAll(func(flag *pflag.Flag) {
if !flag.Changed {
// When adding a flag to a command, include the "--" prefix to indicate that it is a flag
// and not a positional argument. Additionally, when the user presses the TAB key twice after typing
// a flag name, the "--" prefix will appear again, indicating that more flags are available and that
// none of the arguments are positional.
unusedFlags = append(unusedFlags, "--"+flag.Name)
}
})
// Provide a list of flags that can be used in the current command (but have not been used yet)
// for autocompletion suggestions
return unusedFlags, cobra.ShellCompDirectiveNoFileComp
},
}

// cmdValidateFuzzArgs makes sure that there are no positional arguments provided to the fuzz command
func cmdValidateFuzzArgs(cmd *cobra.Command, args []string) error {
// Make sure we have no positional args
if err := cobra.NoArgs(cmd, args); err != nil {
return fmt.Errorf("fuzz does not accept any positional arguments, only flags and their associated values")
}
return nil
Use: "fuzz",
Short: "Starts a fuzzing campaign",
Long: `Starts a fuzzing campaign`,
Args: cmdValidateFuzzArgs,
ValidArgsFunction: cmdValidFuzzArgs,
RunE: cmdRunFuzz,
SilenceUsage: true,
SilenceErrors: true,
}

func init() {
// Add all the flags allowed for the fuzz command
err := addFuzzFlags()
if err != nil {
panic(err)
cmdLogger.Panic("Failed to initialize the fuzz command", err)
}

// Add the fuzz command and its associated flags to the root command
rootCmd.AddCommand(fuzzCmd)
}

// cmdValidFuzzArgs will return which flags and sub-commands are valid for dynamic completion for the fuzz command
func cmdValidFuzzArgs(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
// Gather a list of flags that are available to be used in the current command but have not been used yet
var unusedFlags []string

// Examine all the flags, and add any flags that have not been set in the current command line
// to a list of unused flags
cmd.Flags().VisitAll(func(flag *pflag.Flag) {
if !flag.Changed {
// When adding a flag to a command, include the "--" prefix to indicate that it is a flag
// and not a positional argument. Additionally, when the user presses the TAB key twice after typing
// a flag name, the "--" prefix will appear again, indicating that more flags are available and that
// none of the arguments are positional.
unusedFlags = append(unusedFlags, "--"+flag.Name)
}
})
// Provide a list of flags that can be used in the current command (but have not been used yet)
// for autocompletion suggestions
return unusedFlags, cobra.ShellCompDirectiveNoFileComp
}

// cmdValidateFuzzArgs makes sure that there are no positional arguments provided to the fuzz command
func cmdValidateFuzzArgs(cmd *cobra.Command, args []string) error {
// Make sure we have no positional args
if err := cobra.NoArgs(cmd, args); err != nil {
err = fmt.Errorf("fuzz does not accept any positional arguments, only flags and their associated values")
cmdLogger.Error("Failed to validate args to the fuzz command", err)
return err
}
return nil
}

// cmdRunFuzz executes the CLI fuzz command and navigates through the following possibilities:
// #1: We will search for either a custom config file (via --config) or the default (medusa.json).
// If we find it, read it. If we can't read it, throw an error.
Expand All @@ -73,13 +80,15 @@ func cmdRunFuzz(cmd *cobra.Command, args []string) error {
configFlagUsed := cmd.Flags().Changed("config")
configPath, err := cmd.Flags().GetString("config")
if err != nil {
cmdLogger.Error("Failed to run the fuzz command", err)
return err
}

// If --config was not used, look for `medusa.json` in the current work directory
if !configFlagUsed {
workingDirectory, err := os.Getwd()
if err != nil {
cmdLogger.Error("Failed to run the fuzz command", err)
return err
}
configPath = filepath.Join(workingDirectory, DefaultProjectConfigFilename)
Expand All @@ -91,31 +100,36 @@ func cmdRunFuzz(cmd *cobra.Command, args []string) error {
// Possibility #1: File was found
if existenceError == nil {
// Try to read the configuration file and throw an error if something goes wrong
cmdLogger.Info("Reading the configuration file at: ", colors.Bold, configPath, colors.Reset)
projectConfig, err = config.ReadProjectConfigFromFile(configPath)
if err != nil {
cmdLogger.Error("Failed to run the fuzz command", err)
return err
}
}

// Possibility #2: If the --config flag was used, and we couldn't find the file, we'll throw an error
if configFlagUsed && existenceError != nil {
cmdLogger.Error("Failed to run the fuzz command", err)
return existenceError
}

// Possibility #3: --config flag was not used and medusa.json was not found, so use the default project config
if !configFlagUsed && existenceError != nil {
fmt.Printf("unable to find the config file at %v. will use the default project configuration for the "+
"%v compilation platform instead\n", configPath, DefaultCompilationPlatform)
cmdLogger.Warn(fmt.Sprintf("Unable to find the config file at %v, will use the default project configuration for the "+
"%v compilation platform instead", configPath, DefaultCompilationPlatform))

projectConfig, err = config.GetDefaultProjectConfig(DefaultCompilationPlatform)
if err != nil {
cmdLogger.Error("Failed to run the fuzz command", err)
return err
}
}

// Update the project configuration given whatever flags were set using the CLI
err = updateProjectConfigWithFuzzFlags(cmd, projectConfig)
if err != nil {
cmdLogger.Error("Failed to run the fuzz command", err)
return err
}

Expand All @@ -125,6 +139,7 @@ func cmdRunFuzz(cmd *cobra.Command, args []string) error {
// be in the config directory when running this.
err = os.Chdir(filepath.Dir(configPath))
if err != nil {
cmdLogger.Error("Failed to run the fuzz command", err)
return err
}

Expand Down
Loading

0 comments on commit 4c5c993

Please sign in to comment.