From e2793ba977454416d2d6caa3b9b9e9158a909924 Mon Sep 17 00:00:00 2001 From: alhudz Date: Tue, 9 Jun 2026 16:35:12 +0530 Subject: [PATCH 1/2] guard int32/uint32 map key narrowing in qualifyInternal --- interpreter/attributes.go | 16 ++++++++++------ interpreter/attributes_test.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) 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..daa2a2d9 100644 --- a/interpreter/attributes_test.go +++ b/interpreter/attributes_test.go @@ -396,6 +396,36 @@ func TestAttributesConditionalAttrFalseBranch(t *testing.T) { } } +func TestAttributesNarrowMapKeyQualifier(t *testing.T) { + reg := newTestRegistry(t) + attrs := NewAttributeFactory(containers.DefaultContainer, reg, reg) + vars, _ := NewActivation(map[string]any{ + "i32": map[int32]any{0: "zero"}, + "u32": map[uint32]any{0: "zero"}, + }) + + // 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. + i32 := attrs.AbsoluteAttribute(1, "i32") + i32.AddQualifier(makeQualifier(t, attrs, nil, 2, int64(1)<<32)) + if out, err := i32.Resolve(vars); err == nil { + t.Errorf("i32[1<<32] got %v, wanted no such key error", out) + } + + u32 := attrs.AbsoluteAttribute(3, "u32") + u32.AddQualifier(makeQualifier(t, attrs, nil, 4, uint64(1)<<32)) + if out, err := u32.Resolve(vars); err == nil { + t.Errorf("u32[1<<32] got %v, wanted no such key error", out) + } + + // In-range keys still resolve. + i32ok := attrs.AbsoluteAttribute(5, "i32") + i32ok.AddQualifier(makeQualifier(t, attrs, nil, 6, int64(0))) + if out, err := i32ok.Resolve(vars); err != nil || out != "zero" { + t.Errorf("i32[0] got (%v, %v), wanted (zero, nil)", out, err) + } +} + func TestAttributesOptional(t *testing.T) { reg := newTestRegistry(t, types.ProtoTypeDefs(&proto3pb.TestAllTypes{})) cont, err := containers.NewContainer(containers.Name("ns")) From 7145d7736f1cd411d8d44d269e151fb97fd821a6 Mon Sep 17 00:00:00 2001 From: alhudz Date: Fri, 12 Jun 2026 11:37:40 +0530 Subject: [PATCH 2/2] parameterize narrow map key qualifier test --- interpreter/attributes_test.go | 54 ++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/interpreter/attributes_test.go b/interpreter/attributes_test.go index daa2a2d9..098d7eb5 100644 --- a/interpreter/attributes_test.go +++ b/interpreter/attributes_test.go @@ -399,30 +399,48 @@ func TestAttributesConditionalAttrFalseBranch(t *testing.T) { func TestAttributesNarrowMapKeyQualifier(t *testing.T) { reg := newTestRegistry(t) attrs := NewAttributeFactory(containers.DefaultContainer, reg, reg) - vars, _ := NewActivation(map[string]any{ + 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. - i32 := attrs.AbsoluteAttribute(1, "i32") - i32.AddQualifier(makeQualifier(t, attrs, nil, 2, int64(1)<<32)) - if out, err := i32.Resolve(vars); err == nil { - t.Errorf("i32[1<<32] got %v, wanted no such key error", out) - } - - u32 := attrs.AbsoluteAttribute(3, "u32") - u32.AddQualifier(makeQualifier(t, attrs, nil, 4, uint64(1)<<32)) - if out, err := u32.Resolve(vars); err == nil { - t.Errorf("u32[1<<32] got %v, wanted no such key error", out) + 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"}, } - - // In-range keys still resolve. - i32ok := attrs.AbsoluteAttribute(5, "i32") - i32ok.AddQualifier(makeQualifier(t, attrs, nil, 6, int64(0))) - if out, err := i32ok.Resolve(vars); err != nil || out != "zero" { - t.Errorf("i32[0] got (%v, %v), wanted (zero, nil)", out, err) + 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) + } + }) } }