-
Type:
Bug
-
Resolution: Fixed
-
Priority:
Major - P3
-
Affects Version/s: None
-
Component/s: Query Execution, Query Planning
-
None
-
Query Execution
-
Fully Compatible
-
ALL
-
v8.2
-
QE 2025-10-13
-
200
-
None
-
None
-
None
-
None
-
None
-
None
-
None
BF-39870 is about an invariant failure in FieldPath.h:
HashedFieldName getFieldNameHashed(size_t i) const {
dassert(i < getPathLength());
invariant(_fieldHash[i] != kHashUninitialized); /// fails!
return HashedFieldName{getFieldName(i), _fieldHash[i]};
}
Unfortunately, the stack trace in the BF is hardly usable, so it's unclear from where exactly the getFieldNameHashed() call came and upon which concrete FieldPath it ran.
The preconditions that could lead to the invariant failure are.
- a hashed field name was accessed for a FieldPath without precomputed hashes. This is possible if the FieldPath was originally created without the precomputeHashes flag. The default value of this flag is false in all FieldPath constructors.
- a hashed field name was accessed for a FieldPath with precomputed hashes, but the hash value of the field equals FieldPath::kHashUninitialized.
Although it's unclear if the BF was caused because of the first or the latter issue, the latter issue still seems problematic The getFieldNameHashed() function does not distinguish between not-computed hashes and valid hash values that are equal to kHashUninitialized (i.e. UINT32_MAX).
The hashes are computed here via this expression:
_fieldHash.push_back(precomputeHashes ? FieldNameHasher()(fieldName) : kHashUninitialized);
This is using FieldNameHasher , which uses absl::hash<std::string_view>() underneath. If this hash function happens to return a hash value of UINT32_MAX, then it would be stored as a hash with value equal to kHashUninitialized inside FieldPath::_fieldHash. When calling FieldPath::getFieldNameHashed() for the respective field later, the invariant failure would be triggered.
This should be fixed so that FieldPath can deal with all possible hash values.
The invariant failure should also be replaced with a tassert so that an invalid access does not crash the entire server process, but just the currently running query.