diff --git a/builtin/builtin.go b/builtin/builtin.go index 87e73614..a629b9df 100644 --- a/builtin/builtin.go +++ b/builtin/builtin.go @@ -222,6 +222,9 @@ var Builtins = []*Function{ { Name: "trimPrefix", Func: func(args ...any) (any, error) { + if len(args) == 0 { + return nil, fmt.Errorf("not enough arguments to call trimPrefix") + } s := " " if len(args) == 2 { s = args[1].(string) @@ -236,6 +239,9 @@ var Builtins = []*Function{ { Name: "trimSuffix", Func: func(args ...any) (any, error) { + if len(args) == 0 { + return nil, fmt.Errorf("not enough arguments to call trimSuffix") + } s := " " if len(args) == 2 { s = args[1].(string) @@ -312,6 +318,9 @@ var Builtins = []*Function{ { Name: "repeat", Safe: func(args ...any) (any, uint, error) { + if len(args) < 2 { + return nil, 0, fmt.Errorf("not enough arguments to call repeat") + } s := args[0].(string) n := runtime.ToInt(args[1]) if n < 0 { @@ -327,6 +336,9 @@ var Builtins = []*Function{ { Name: "join", Func: func(args ...any) (any, error) { + if len(args) == 0 { + return nil, fmt.Errorf("not enough arguments to call join") + } glue := "" if len(args) == 2 { glue = args[1].(string) @@ -354,6 +366,9 @@ var Builtins = []*Function{ { Name: "indexOf", Func: func(args ...any) (any, error) { + if len(args) < 2 { + return nil, fmt.Errorf("not enough arguments to call indexOf") + } return strings.Index(args[0].(string), args[1].(string)), nil }, Types: types(strings.Index), @@ -361,6 +376,9 @@ var Builtins = []*Function{ { Name: "lastIndexOf", Func: func(args ...any) (any, error) { + if len(args) < 2 { + return nil, fmt.Errorf("not enough arguments to call lastIndexOf") + } return strings.LastIndex(args[0].(string), args[1].(string)), nil }, Types: types(strings.LastIndex), @@ -368,6 +386,9 @@ var Builtins = []*Function{ { Name: "hasPrefix", Func: func(args ...any) (any, error) { + if len(args) < 2 { + return nil, fmt.Errorf("not enough arguments to call hasPrefix") + } return strings.HasPrefix(args[0].(string), args[1].(string)), nil }, Types: types(strings.HasPrefix), @@ -375,6 +396,9 @@ var Builtins = []*Function{ { Name: "hasSuffix", Func: func(args ...any) (any, error) { + if len(args) < 2 { + return nil, fmt.Errorf("not enough arguments to call hasSuffix") + } return strings.HasSuffix(args[0].(string), args[1].(string)), nil }, Types: types(strings.HasSuffix), @@ -436,6 +460,9 @@ var Builtins = []*Function{ { Name: "toJSON", Func: func(args ...any) (any, error) { + if len(args) == 0 { + return nil, fmt.Errorf("not enough arguments to call toJSON") + } b, err := json.MarshalIndent(args[0], "", " ") if err != nil { return nil, err @@ -447,6 +474,9 @@ var Builtins = []*Function{ { Name: "fromJSON", Func: func(args ...any) (any, error) { + if len(args) == 0 { + return nil, fmt.Errorf("not enough arguments to call fromJSON") + } var v any err := json.Unmarshal([]byte(args[0].(string)), &v) if err != nil { @@ -459,6 +489,9 @@ var Builtins = []*Function{ { Name: "toBase64", Func: func(args ...any) (any, error) { + if len(args) == 0 { + return nil, fmt.Errorf("not enough arguments to call toBase64") + } return base64.StdEncoding.EncodeToString([]byte(args[0].(string))), nil }, Types: types(new(func(string) string)), @@ -466,6 +499,9 @@ var Builtins = []*Function{ { Name: "fromBase64", Func: func(args ...any) (any, error) { + if len(args) == 0 { + return nil, fmt.Errorf("not enough arguments to call fromBase64") + } b, err := base64.StdEncoding.DecodeString(args[0].(string)) if err != nil { return nil, err @@ -505,6 +541,9 @@ var Builtins = []*Function{ { Name: "duration", Func: func(args ...any) (any, error) { + if len(args) == 0 { + return nil, fmt.Errorf("not enough arguments to call duration") + } return time.ParseDuration(args[0].(string)) }, Types: types(time.ParseDuration), @@ -512,10 +551,16 @@ var Builtins = []*Function{ { Name: "date", Func: func(args ...any) (any, error) { + if len(args) == 0 { + return nil, fmt.Errorf("not enough arguments to call date") + } tz, ok := args[0].(*time.Location) if ok { args = args[1:] } + if len(args) == 0 { + return nil, fmt.Errorf("not enough arguments to call date") + } date := args[0].(string) if len(args) == 2 { @@ -585,6 +630,9 @@ var Builtins = []*Function{ { Name: "timezone", Func: func(args ...any) (any, error) { + if len(args) == 0 { + return nil, fmt.Errorf("not enough arguments to call timezone") + } tz, err := time.LoadLocation(args[0].(string)) if err != nil { return nil, err @@ -596,6 +644,9 @@ var Builtins = []*Function{ { Name: "first", Func: func(args ...any) (any, error) { + if len(args) != 1 { + return nil, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args)) + } defer func() { if r := recover(); r != nil { return @@ -619,6 +670,9 @@ var Builtins = []*Function{ { Name: "last", Func: func(args ...any) (any, error) { + if len(args) != 1 { + return nil, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args)) + } defer func() { if r := recover(); r != nil { return diff --git a/test/fuzz/fuzz_test.go b/test/fuzz/fuzz_test.go index e12c4d8e..ae511ac9 100644 --- a/test/fuzz/fuzz_test.go +++ b/test/fuzz/fuzz_test.go @@ -66,6 +66,7 @@ func FuzzExpr(f *testing.F) { regexp.MustCompile(`invalid order .*, expected asc or desc`), regexp.MustCompile(`unknown order, use asc or desc`), regexp.MustCompile(`cannot use .* as a key for groupBy: type is not comparable`), + regexp.MustCompile(`not enough arguments to call .*`), } env := NewEnv() diff --git a/testdata/generated.txt b/testdata/generated.txt index 5166aeb8..d0d0f0b8 100644 --- a/testdata/generated.txt +++ b/testdata/generated.txt @@ -763,7 +763,6 @@ $env not contains $env?.[Bar]?.add() $env not contains $env?.[Bar]?.ok $env not contains $env?.[String?.str] $env not contains $env?.[String] -$env not contains $env?.[first(foobar, greet)] $env not contains $env?.[foobar?.array()] $env not contains $env?.[foobar] $env not contains $env?.[toJSON(foobar)] @@ -3513,7 +3512,6 @@ $env?.[Bar]?.str(f64) $env?.[Bar]?.str(f64, array) $env?.[Bar]?.str(foobar) $env?.[Bar]?.str(greet) -$env?.[Bar]?.str(list | first(true, foobar)) $env?.[Bar]?.str(list) $env?.[Bar]?.str(nil) $env?.[Bar]?.str.Bar @@ -3645,7 +3643,6 @@ $env?.[String]?.String(foobar) $env?.[String]?.String(foobar, $env) $env?.[String]?.String(foobar?.[list])?.str() $env?.[String]?.String(greet) -$env?.[String]?.String(last($env, String)) $env?.[String]?.String(ok && foobar) $env?.[String]?.String.add $env?.[String]?.String.split(false, add).str.array @@ -6984,7 +6981,6 @@ $env[:str] not in foo || true 0 == $env?.[Bar | get(foo)] 0 == $env?.[Bar] 0 == $env?.[String] -0 == $env?.[first(0, ok)] 0 == $env?.[foobar] 0 == $env?.[foobar]?.add 0 == $env?.[str] @@ -18596,7 +18592,6 @@ foo not in $env?.[foobar?.f64] foo not in $env?.[foobar?.foo] foo not in $env?.[foobar] foo not in $env?.[foobar]?.[greet] -foo not in $env?.[nil | last(foobar)] foo not in $env?.[nil] foo not in $env?.foobar foo not in $env?.foobar?.greet(foobar) @@ -28092,7 +28087,6 @@ nil != $env?.Bar?.list() nil != $env?.Bar?.str() nil != $env?.String nil != $env?.String?.[i] -nil != $env?.[1.0 | first(nil)] nil != $env?.[Bar] nil != $env?.[Bar]?.Bar nil != $env?.[String] @@ -36587,7 +36581,6 @@ true in $env?.String true in $env?.[Bar] true in $env?.[String] true in $env?.[first(foobar)] -true in $env?.[foobar | last(nil)] true in $env?.[foobar] true not in $env?.Bar true not in $env?.String