diff --git a/gnovm/pkg/gnolang/fuzz_test.go b/gnovm/pkg/gnolang/fuzz_test.go index 977c7453b90..73f7b2db797 100644 --- a/gnovm/pkg/gnolang/fuzz_test.go +++ b/gnovm/pkg/gnolang/fuzz_test.go @@ -1,11 +1,15 @@ package gnolang import ( + "context" + "encoding/json" "os" + "os/exec" "path/filepath" "runtime" "strings" "testing" + "time" "github.com/cockroachdb/apd/v3" ) @@ -87,3 +91,79 @@ func FuzzParseFile(f *testing.F) { _, _ = ParseFile("a.go", goFileContents) }) } + +func FuzzDoOpEvalBaseConversion(f *testing.F) { + if testing.Short() { + f.Skip("Skipping in -short mode") + } + + // 1. Add the seeds. + seeds := []*BasicLitExpr{ + {Kind: INT, Value: "9223372036854775807"}, + {Kind: INT, Value: "0"}, + {Kind: INT, Value: "0777"}, + {Kind: INT, Value: "0xDEADBEEF"}, + {Kind: INT, Value: "0o123"}, + {Kind: INT, Value: "0b111111111111111111111111111111111111111111111111111111111111111"}, + {Kind: FLOAT, Value: "0.00001111"}, + {Kind: FLOAT, Value: "9999.12"}, + {Kind: STRING, Value: `"9999.12"`}, + {Kind: STRING, Value: `"aaaaaaaaaaa "`}, + {Kind: STRING, Value: `"🚨🌎"`}, + } + + for _, seed := range seeds { + blob, err := json.Marshal(seed) + if err != nil { + panic(err) + } + f.Add(blob) + } + + // 2. Fuzz it. + f.Fuzz(func(t *testing.T, basicLitExprBlob []byte) { + expr := new(BasicLitExpr) + if err := json.Unmarshal(basicLitExprBlob, expr); err != nil { + return + } + + defer func() { + r := recover() + if r == nil { + return + } + + switch { + case strings.Contains(fmt.Sprintf("%s", r), "unexpected lit kind"): + return + + default: + if !basicLitExprIsValidGoValue(t, expr) { + return + } + panic(r) + } + }() + + m := NewMachine("test", nil) + m.PushExpr(expr) + m.doOpEval() + _ = m.PopValue() + }) +} + +func basicLitExprIsValidGoValue(t *testing.T, lit *BasicLitExpr) bool { + tempDir := t.TempDir() + file := filepath.Join(tempDir, "basic_lit_check.go") + var craftedGo = []byte(fmt.Sprintf(`package main +var _ = %s +func main() {}`, lit.Value)) + if err := os.WriteFile(file, craftedGo, 0755); err != nil { + panic(err) + } + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + err := exec.CommandContext(ctx, "go", "run", file).Run() + return err == nil +}