Skip to content

runtime: unbounded Swiss map directory growth and OOM on inserting >896 keys with identical hash #81299

Description

@nicholashusin

This was originally reported to us as a security issue. However, we do not see practical ways to exploit this given the niche prerequisite.

Minimal repro:

type Key [5]any

func makeKeys(count int) []Key {
	values := []any{int(0), uint(0), int64(0), uint64(0)}
	keys := make([]Key, count)
	for n := range keys {
		x := n
		for i := range keys[n] {
			keys[n][i] = values[x&3]
			x >>= 2
		}
	}
	return keys
}

func main() {
	fmt.Println("Go version:", runtime.Version())
	m := make(map[Key]struct{})

	// 896 keys succeed and fill the initial table
	for _, k := range makeKeys(896) {
		m[k] = struct{}{}
	}
	fmt.Printf("Inserted 896 keys successfully (map len=%d)\n", len(m))

	// Inserting the 897th identical-hash key triggers an infinite split loop & OOM
	fmt.Println("Inserting 897th key...")
	m[makeKeys(897)[896]] = struct{}{}
	fmt.Println("Finished (unreachable)")
}

Note that this only affect applications that:

  • use a map keyed by a collection of interfaces, such as map[[5]any]T.
  • accept data over a serializer like encoding/gob that lets an untrusted client choose the specific concrete types (e.g., mixing int(0), uint(0), int64(0), and uint64(0))

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.compiler/runtimeIssues related to the Go compiler and/or runtime.

Type

No type

Projects

Relationships

None yet

Development

No branches or pull requests

Issue actions