package fuzz import ( _ "embed" "regexp" "strings" "testing" "github.com/expr-lang/expr" ) //go:embed fuzz_corpus.txt var fuzzCorpus string func FuzzExpr(f *testing.F) { corpus := strings.Split(strings.TrimSpace(fuzzCorpus), "\n") for _, s := range corpus { f.Add(s) } skip := []*regexp.Regexp{ regexp.MustCompile(`cannot fetch .* from .*`), regexp.MustCompile(`cannot get .* from .*`), regexp.MustCompile(`cannot slice`), regexp.MustCompile(`slice index out of range`), regexp.MustCompile(`error parsing regexp`), regexp.MustCompile(`integer divide by zero`), regexp.MustCompile(`interface conversion`), regexp.MustCompile(`invalid argument for .*`), regexp.MustCompile(`invalid character`), regexp.MustCompile(`invalid operation`), regexp.MustCompile(`invalid duration`), regexp.MustCompile(`time: missing unit in duration`), regexp.MustCompile(`time: unknown unit .* in duration`), regexp.MustCompile(`unknown time zone`), regexp.MustCompile(`json: unsupported value`), regexp.MustCompile(`unexpected end of JSON input`), regexp.MustCompile(`memory budget exceeded`), regexp.MustCompile(`using interface \{} as type .*`), regexp.MustCompile(`reflect.Value.MapIndex: value of type .* is not assignable to type .*`), regexp.MustCompile(`reflect: Call using .* as type .*`), regexp.MustCompile(`reflect: Call with too few input arguments`), regexp.MustCompile(`reflect: call of reflect.Value.Call on .* Value`), regexp.MustCompile(`reflect: call of reflect.Value.Index on map Value`), regexp.MustCompile(`reflect: call of reflect.Value.Len on .* Value`), regexp.MustCompile(`reflect: string index out of range`), regexp.MustCompile(`strings: negative Repeat count`), regexp.MustCompile(`strings: illegal bytes to escape`), regexp.MustCompile(`operator "in" not defined on int`), regexp.MustCompile(`invalid date .*`), regexp.MustCompile(`cannot parse .* as .*`), regexp.MustCompile(`operator "in" not defined on .*`), regexp.MustCompile(`cannot sum .*`), regexp.MustCompile(`index out of range: .* \(array length is .*\)`), regexp.MustCompile(`cannot use as argument \(type .*\) to call .*`), regexp.MustCompile(`illegal base64 data at input byte .*`), } env := NewEnv() fn := Func() f.Fuzz(func(t *testing.T, code string) { if len(code) > 1000 { t.Skip("too long code") } program, err := expr.Compile(code, expr.Env(env), fn) if err != nil { t.Skipf("compile error: %s", err) } _, err = expr.Run(program, env) if err != nil { for _, r := range skip { if r.MatchString(err.Error()) { t.Skipf("skip error: %s", err) return } } t.Errorf("%s", err) } }) }