Skip to content

Commit 9365454

Browse files
dgryskideadprogram
authored andcommitted
src/runtime: prevent overflow when calculating hashmap growth limits
1 parent 050d516 commit 9365454

File tree

1 file changed

+18
-6
lines changed

1 file changed

+18
-6
lines changed

src/runtime/hashmap.go

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,15 +109,27 @@ func hashmapKeyHashAlg(alg hashmapAlgorithm) func(key unsafe.Pointer, n uintptr)
109109
}
110110

111111
func hashmapShouldGrow(m *hashmap) bool {
112-
if m.bucketBits == 32 {
113-
// can't grow any more
114-
return false
112+
// with 29 bucket bits, we have potentially 8*(1 << 29) == 2^32 elements
113+
if m.bucketBits <= 29 {
114+
// "maximum" number of elements is 0.75 * buckets * elements per bucket
115+
// to avoid overflow, this is calculated as
116+
// max = 3 * (1/4 * buckets * elements per bucket)
117+
// = 3 * (buckets * (elements per bucket)/4)
118+
// = 3 * (buckets * (8/4)
119+
// = 3 * (buckets * 2)
120+
// = 6 * buckets
121+
max := (uintptr(6) << m.bucketBits)
122+
return m.count > max
115123
}
116124

117-
// "maximum" number of elements is 0.75 * buckets * elements per bucket
118-
max := uintptr((3 * ((1 << m.bucketBits) * 8)) / 4)
125+
if m.bucketBits == 30 && m.count > uintptr(0xe0000000) {
126+
return true
127+
}
119128

120-
return m.count > max
129+
// bucketBits == 32 will cause overflow problems on 32-bit platforms, so we limit it to 31.
130+
// We're also likely to overflow the `int`-sized map length, causing other issues.
131+
132+
return false
121133
}
122134

123135
// Return the number of entries in this hashmap, called from the len builtin.

0 commit comments

Comments
 (0)