From ca0a8da5c2479184554c284ac3d5bc37b448a705 Mon Sep 17 00:00:00 2001 From: 2pac Date: Wed, 30 Apr 2025 00:39:12 +0200 Subject: [PATCH] fix(785): `get` to work when return is `nil` --- builtin/lib.go | 4 ++++ test/fuzz/fuzz_corpus.txt | 5 +++++ test/issues/785/issue_test.go | 38 +++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 test/issues/785/issue_test.go diff --git a/builtin/lib.go b/builtin/lib.go index 5a70a6b91..579393161 100644 --- a/builtin/lib.go +++ b/builtin/lib.go @@ -374,6 +374,10 @@ func get(params ...any) (out any, err error) { i := params[1] v := reflect.ValueOf(from) + if from == nil { + return nil, nil + } + if v.Kind() == reflect.Invalid { panic(fmt.Sprintf("cannot fetch %v from %T", i, from)) } diff --git a/test/fuzz/fuzz_corpus.txt b/test/fuzz/fuzz_corpus.txt index 72afdf6ce..e1395c7b4 100644 --- a/test/fuzz/fuzz_corpus.txt +++ b/test/fuzz/fuzz_corpus.txt @@ -7221,6 +7221,11 @@ get(true ? i64 : greet, i32) get(true ? score : true, half)?.half get(true ? true : i, f64) get({"foo": foo, "bar": false}, type(i)) +get(nil, "a") +get({}, "a") +get(nil, "a") == nil +get({}, "a") == nil +({} | get("a") | get("b")) == nil greet greet != greet greet != greet != ok diff --git a/test/issues/785/issue_test.go b/test/issues/785/issue_test.go new file mode 100644 index 000000000..4e4f9e53d --- /dev/null +++ b/test/issues/785/issue_test.go @@ -0,0 +1,38 @@ +package issue_test + +import ( + "testing" + + "github.com/expr-lang/expr" + "github.com/expr-lang/expr/internal/testify/require" +) + +func TestIssue785(t *testing.T) { + emptyMap := map[string]any{} + + env := map[string]interface{}{ + "empty_map": emptyMap, + } + + { + code := `get(empty_map, "non_existing_key") | get("some_key") | get("another_key") | get("yet_another_key") | get("last_key")` + + program, err := expr.Compile(code, expr.Env(env)) + require.NoError(t, err) + + output, err := expr.Run(program, env) + require.NoError(t, err) + require.Equal(t, nil, output) + } + + { + code := `{} | get("non_existing_key") | get("some_key") | get("another_key") | get("yet_another_key") | get("last_key")` + + program, err := expr.Compile(code, expr.Env(env)) + require.NoError(t, err) + + output, err := expr.Run(program, env) + require.NoError(t, err) + require.Equal(t, nil, output) + } +}