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/expr_test.go b/expr_test.go index 4d3736a97..faa5cae6d 100644 --- a/expr_test.go +++ b/expr_test.go @@ -2724,3 +2724,24 @@ func TestExpr_wierd_cases(t *testing.T) { require.Error(t, err) require.Contains(t, err.Error(), "unknown name A") } + +func TestIssue785_get_nil(t *testing.T) { + exprStrs := []string{ + `get(nil, "a")`, + `get({}, "a")`, + `get(nil, "a")`, + `get({}, "a")`, + `({} | get("a") | get("b"))`, + } + + for _, exprStr := range exprStrs { + t.Run("get returns nil", func(t *testing.T) { + env := map[string]interface{}{} + + result, err := expr.Eval(exprStr, env) + require.NoError(t, err) + + require.Equal(t, nil, result) + }) + } +} 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) + } +}