Bug 305864
| Summary: | [CSS] Crash due to release assert in HashTable when MatchedDeclarationsCache::computeHash() returns 0xFFFFFFFF | ||
|---|---|---|---|
| Product: | WebKit | Reporter: | David Kilzer (:ddkilzer) <ddkilzer> |
| Component: | CSS | Assignee: | David Kilzer (:ddkilzer) <ddkilzer> |
| Status: | RESOLVED FIXED | ||
| Severity: | Normal | CC: | koivisto, webkit-bug-importer |
| Priority: | P2 | Keywords: | InRadar |
| Version: | WebKit Nightly Build | ||
| Hardware: | Unspecified | ||
| OS: | Unspecified | ||
| See Also: | https://bugs.webkit.org/show_bug.cgi?id=295927 | ||
| Bug Depends on: | 232930, 267447 | ||
| Bug Blocks: | |||
David Kilzer (:ddkilzer)
The computeHash() function in Source/WebCore/style/MatchedDeclarationsCache.cpp returns the result of WTF::computeHash() directly without calling AlreadyHashed::avoidDeletedValue().
The call chain is:
WTF::computeHash() -> SuperFastHash::hash() -> StringHasher::finalize() -> avoidZero(avalancheBits(hash))
The avalancheBits() function can return the full range of 32-bit values, including 0xFFFFFFFF. While avoidZero() prevents returning 0 (the empty sentinel), it does not prevent returning 0xFFFFFFFF (the deleted sentinel for unsigned hash keys).
When the hash value equals 0xFFFFFFFF and is inserted into HashMap<unsigned, ..., AlreadyHashed>, it triggers RELEASE_ASSERT in checkHashTableKey().
This bug is not testable because the hash includes pointer values that vary at runtime:
```
// MatchedDeclarationsCache.cpp:137
unsigned hash = WTF::computeHash(matchResult, &inheritedCustomProperties);
// ^^^ pointer value
// MatchResult.h:120-121
add(hasher,
matchedProperties.properties.ptr(), // <-- pointer value
matchedProperties.linkMatchType,
...
);
```
Crash stack:
```
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread:
0 WebCore WTFCrashWithInfo + 24 (Assertions.h:969)
1 WebCore void WTF::checkHashTableKey<...> + 24 (HashTable.h:374)
2 WebCore WTF::HashTable<...>::inlineLookup<...> + 24 (HashTable.h:670)
3 WebCore WTF::HashTable<...>::lookup<...> + 24 (HashTable.h:662)
4 WebCore WTF::HashTable<...>::find<...> + 48 (HashTable.h:1004)
5 WebCore WTF::HashTable<...>::find<...> + 48 (HashTable.h:515)
6 WebCore WTF::HashMap<...>::find + 48 (HashMap.h:360)
7 WebCore WebCore::Style::MatchedDeclarationsCache::find + 48 (MatchedDeclarationsCache.cpp:143)
8 WebCore WebCore::Style::Resolver::applyMatchedProperties + 1284 (StyleResolver.cpp:706)
9 WebCore WebCore::Style::Resolver::unadjustedStyleForElement + 3532 (StyleResolver.cpp:341)
10 WebCore WebCore::SVGElement::resolveCustomStyle + 44 (SVGElement.cpp:647)
[...]
```
<rdar://118164567>
| Attachments | ||
|---|---|---|
| Add attachment proposed patch, testcase, etc. |
David Kilzer (:ddkilzer)
The fix is to wrap the return value with AlreadyHashed::avoidDeletedValue() to transform 0xFFFFFFFF to 0x7FFFFFFF:
```
return AlreadyHashed::avoidDeletedValue(WTF::computeHash(matchResult, &inheritedCustomProperties));
```
This follows the existing pattern in SharedStringHash.cpp and ImmutableStyleProperties.cpp.
David Kilzer (:ddkilzer)
Pull request: https://github.com/WebKit/WebKit/pull/56925
EWS
Committed 305989@main (45684cc85f9f): <https://commits.webkit.org/305989@main>
Reviewed commits have been landed. Closing PR #56925 and removing active labels.