Skip to content

Commit

Permalink
Fix nil key check in map (#351)
Browse files Browse the repository at this point in the history
  • Loading branch information
antonmedv authored Mar 9, 2023
1 parent 5613693 commit df2cccd
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 6 deletions.
2 changes: 1 addition & 1 deletion checker/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ func (v *visitor) MemberNode(node *ast.MemberNode) (reflect.Type, info) {
return anyType, info{}

case reflect.Map:
if !prop.AssignableTo(base.Key()) && !isAny(prop) {
if prop != nil && !prop.AssignableTo(base.Key()) && !isAny(prop) {
return v.error(node.Property, "cannot use %v to get an element from %v", prop, base)
}
t, c := deref(base.Elem())
Expand Down
39 changes: 39 additions & 0 deletions expr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1772,6 +1772,45 @@ func TestRun_NilCoalescingOperator(t *testing.T) {
})
}

func TestEval_nil_in_maps(t *testing.T) {
env := map[string]interface{}{
"m": map[interface{}]interface{}{nil: "bar"},
"empty": map[interface{}]interface{}{},
}
t.Run("nil key exists", func(t *testing.T) {
p, err := expr.Compile(`m[nil]`, expr.Env(env))
assert.NoError(t, err)

out, err := expr.Run(p, env)
assert.NoError(t, err)
assert.Equal(t, "bar", out)
})
t.Run("no nil key", func(t *testing.T) {
p, err := expr.Compile(`empty[nil]`, expr.Env(env))
assert.NoError(t, err)

out, err := expr.Run(p, env)
assert.NoError(t, err)
assert.Equal(t, nil, out)
})
t.Run("nil in m", func(t *testing.T) {
p, err := expr.Compile(`nil in m`, expr.Env(env))
assert.NoError(t, err)

out, err := expr.Run(p, env)
assert.NoError(t, err)
assert.Equal(t, true, out)
})
t.Run("nil in empty", func(t *testing.T) {
p, err := expr.Compile(`nil in empty`, expr.Env(env))
assert.NoError(t, err)

out, err := expr.Run(p, env)
assert.NoError(t, err)
assert.Equal(t, false, out)
})
}

// Mock types

type mockEnv struct {
Expand Down
20 changes: 15 additions & 5 deletions vm/runtime/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,12 @@ func Fetch(from, i interface{}) interface{} {
}

case reflect.Map:
value := v.MapIndex(reflect.ValueOf(i))
var value reflect.Value
if i == nil {
value = v.MapIndex(reflect.Zero(v.Type().Key()))
} else {
value = v.MapIndex(reflect.ValueOf(i))
}
if value.IsValid() {
return value.Interface()
} else {
Expand Down Expand Up @@ -221,11 +226,16 @@ func In(needle interface{}, array interface{}) bool {
return false

case reflect.Map:
n := reflect.ValueOf(needle)
if !n.IsValid() {
panic(fmt.Sprintf("cannot use %T as index to %T", needle, array))
var value reflect.Value
if needle == nil {
value = v.MapIndex(reflect.Zero(v.Type().Key()))
} else {
n := reflect.ValueOf(needle)
if !n.IsValid() {
panic(fmt.Sprintf("cannot use %T as index to %T", needle, array))
}
value = v.MapIndex(n)
}
value := v.MapIndex(n)
if value.IsValid() {
return true
}
Expand Down

0 comments on commit df2cccd

Please sign in to comment.