Skip to content

Hash sentinel can collapse attribute sets to empty #8400

@pellared

Description

@pellared

Description

go.opentelemetry.io/otel/attribute can treat a non-empty attribute set as empty when its computed 64-bit FNV-1a hash is zero. The Set/Distinct implementation reserves hash == 0 as an invalid sentinel, but hashKVs can legitimately return zero and newSet stores that value without remapping it.

When a non-empty set has hash == 0, methods such as Len, Get, and Value return empty results, and Equivalent collapses it to the empty set. This can cause telemetry using crafted attributes to lose labels or merge into the empty label set.

Steps To Reproduce

   func TestZeroHashNonEmptySetShouldNotCollapse(t *testing.T) {
   	kvs := []KeyValue{String("attacker", "controlled")}
   	s := Set{
   		hash: 0,
   		data: computeDataFixed(kvs),
   	}

   	if got := s.Len(); got != 1 {
   		t.Errorf("Len() = %d, want 1 for non-empty data", got)
   	}
   	if _, ok := s.Value("attacker"); !ok {
   		t.Errorf("Value() omitted attacker-controlled attribute")
   	}
   	if s.Equivalent() == (Distinct{hash: emptySet.hash}) {
   		t.Errorf("Equivalent() collapsed non-empty zero-hash set to emptySet")
   	}
   }

Expected behavior

Attribute-set hashing should never allow a non-empty set to be represented with the reserved empty/invalid sentinel. If hashKVs returns zero, the set implementation should remap it to a non-zero value or track validity separately so Len, Get, Value, and Equivalent preserve the non-empty attributes.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingpkg:attributeRelated to the attribute package

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions