Fix/hashvalue unknown type panic - #8723
sarthaks2378 wants to merge 2 commits into
Conversation
hashValue's default case panicked when a Value's Type() didn't match any of the known constants. This is unreachable through the public API, since every exported constructor sets vtype to one of the known constants, but Value.String and Value.AsInterface already handle this same unreachable case defensively (returning "unknown" / an empty interface value) instead of panicking. Make hashValue consistent with those two: fall back to a new stable unknownID hash instead of panicking, so that Distinct()/Set hashing can never crash a caller. Also drops the now-unused fmt import.
Adds TestHashValueUnknownType, which constructs a Value with an out-of-range vtype (only possible via package-internal field access, since the field is unexported) and asserts hashValue no longer panics and instead returns a stable hash that doesn't depend on the other Value fields.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #8723 +/- ##
=====================================
Coverage 84.0% 84.1%
=====================================
Files 329 329
Lines 26068 26066 -2
=====================================
+ Hits 21917 21924 +7
+ Misses 3769 3760 -9
Partials 382 382
🚀 New features to boost your workflow:
|
|
Thanks for taking this on. We don't want to remove this panic. Hashing Since removing this invariant check is the purpose of the PR, I don’t think there is a change to request here. I’m going to close this PR. If other maintainers disagree we can re-evaluate. |
Fixes #8047
Problem
hashValue'sdefaultcase panics whenever aValue'sType()doesn'tmatch any of the known type constants:
https://github.com/open-telemetry/opentelemetry-go/blob/main/attribute/hash.go#L284-L289
This is unreachable through the public API today — every exported
constructor in this package (
BoolValue,IntValue,StringValue, ...)sets
vtypeto one of the handled constants, so no user-facing code pathcan currently trigger it.
However,
Value.StringandValue.AsInterfacealready treat this exactsame "unreachable" case defensively, returning
"unknown"and an emptyinterface value respectively instead of panicking:
https://github.com/open-telemetry/opentelemetry-go/blob/main/attribute/value.go#L470-L473
https://github.com/open-telemetry/opentelemetry-go/blob/main/attribute/value.go#L428-L431
hashValuewas the one remaining place (per #8047 and the discussion on#8038) that still panics instead of degrading gracefully. Since
hashValuebacks
Set.Equivalent,Hasher.Distinct, and ultimately attribute-setdeduplication throughout the SDK, a panic here is more consequential than
in
String/AsInterface: it would propagate out ofNewSet/Hasher.Writeand crash the caller.
Fix
unknownIDhash constant (following the existing pattern ofboolID,emptyID, etc.) and hash that in thedefaultcase instead ofbuilding an error message and panicking.
fmtimport fromattribute/hash.go.TestHashValueUnknownType, which constructs aValuewith anout-of-range
vtype(only possible via package-internal field access,since the field is unexported) and asserts:
hashValueno longer panics for it.Value's other fields (numeric,stringly), since none of them are meaningful once the type isunknown.
Why this is safe
reachable
Valuetypes (BOOL,INT64,FLOAT64,STRING, the slicetypes,
SLICE,MAP,EMPTY) — this PR only touches thedefaultbranch that is currently unreachable.
the hot path for any real type.
should, since it's unreachable) would instead get a valid, stable
Distinct/Sethash.Test plan
go test ./attribute/...— all existing tests pass.go vet ./attribute/...andgofmt -l attribute/— clean.TestHashValueUnknownTypeexercises the previously-panicking pathdirectly.