diff --git a/interpreter/attributes.go b/interpreter/attributes.go index 107b5eea..d9e6adef 100644 --- a/interpreter/attributes.go +++ b/interpreter/attributes.go @@ -964,9 +964,11 @@ func (q *intQualifier) qualifyInternal(vars Activation, obj any, presenceTest, p } case map[int32]any: isMap = true - obj, isKey := o[int32(i)] - if isKey { - return obj, true, nil + if i32 := int32(i); int64(i32) == i { + obj, isKey := o[i32] + if isKey { + return obj, true, nil + } } case map[int64]any: isMap = true @@ -1089,9 +1091,11 @@ func (q *uintQualifier) qualifyInternal(vars Activation, obj any, presenceTest, return obj, true, nil } case map[uint32]any: - obj, isKey := o[uint32(u)] - if isKey { - return obj, true, nil + if u32 := uint32(u); uint64(u32) == u { + obj, isKey := o[u32] + if isKey { + return obj, true, nil + } } case map[uint64]any: obj, isKey := o[u] diff --git a/interpreter/attributes_test.go b/interpreter/attributes_test.go index aebe01aa..098d7eb5 100644 --- a/interpreter/attributes_test.go +++ b/interpreter/attributes_test.go @@ -396,6 +396,54 @@ func TestAttributesConditionalAttrFalseBranch(t *testing.T) { } } +func TestAttributesNarrowMapKeyQualifier(t *testing.T) { + reg := newTestRegistry(t) + attrs := NewAttributeFactory(containers.DefaultContainer, reg, reg) + vars, err := NewActivation(map[string]any{ + "i32": map[int32]any{0: "zero"}, + "u32": map[uint32]any{0: "zero"}, + }) + if err != nil { + t.Fatalf("NewActivation() failed: %v", err) + } + // An index outside the key type's range must not be truncated into a + // matching key. int32(1<<32) and uint32(1<<32) both wrap to 0. + tests := []struct { + varName string + qual any + out any + err error + }{ + {varName: "i32", qual: int64(1) << 32, err: errors.New("no such key: 4294967296")}, + {varName: "u32", qual: uint64(1) << 32, err: errors.New("no such key: 4294967296")}, + {varName: "i32", qual: int64(0), out: "zero"}, + {varName: "u32", qual: uint64(0), out: "zero"}, + } + for i, tst := range tests { + tc := tst + t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { + attr := attrs.AbsoluteAttribute(1, tc.varName) + attr.AddQualifier(makeQualifier(t, attrs, nil, 2, tc.qual)) + out, err := attr.Resolve(vars) + if err != nil { + if tc.err == nil { + t.Fatalf("attr.Resolve() failed: %v", err) + } + if tc.err.Error() != err.Error() { + t.Fatalf("attr.Resolve() errored with %v, wanted error %v", err, tc.err) + } + return + } + if tc.err != nil { + t.Fatalf("attr.Resolve() got %v, wanted error %v", out, tc.err) + } + if out != tc.out { + t.Errorf("attr.Resolve() got %v, wanted %v", out, tc.out) + } + }) + } +} + func TestAttributesOptional(t *testing.T) { reg := newTestRegistry(t, types.ProtoTypeDefs(&proto3pb.TestAllTypes{})) cont, err := containers.NewContainer(containers.Name("ns"))