From 50eb82660bb642408c5f894de1703b9decbecca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Stuchl=C3=ADk?= Date: Tue, 17 Mar 2026 19:15:19 +0100 Subject: [PATCH] fix: data race in ehash due to unsynchronized lazy init of Map.typ --- go.mod | 2 +- map.go | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 5714ccc..2e9e8af 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ module github.com/lrita/cmap -go 1.18 +go 1.19 diff --git a/map.go b/map.go index 46334bb..2bbd9f5 100644 --- a/map.go +++ b/map.go @@ -16,7 +16,7 @@ import ( type Map[K comparable, V any] struct { lock sync.Mutex inode unsafe.Pointer // *inode2 - typ *rtype + typ atomic.Pointer[rtype] count int64 } @@ -400,23 +400,23 @@ func efaceOf(ep *any) *eface { } func (m *Map[K, V]) ehash(i K) uintptr { - if m.typ == nil { - func() { - m.lock.Lock() - defer m.lock.Unlock() - if m.typ == nil { - // if K is interface type, then the direct reflect.TypeOf(K).Kind return reflect.Ptr - if typ := reflect.TypeOf(&i); typ.Elem().Kind() == reflect.Interface { - panic("not support interface type") - } - var e any = i - m.typ = efaceOf(&e).typ + typ := m.typ.Load() + if typ == nil { + m.lock.Lock() + if m.typ.Load() == nil { + // if K is interface type, then the direct reflect.TypeOf(K).Kind return reflect.Ptr + if typ := reflect.TypeOf(&i); typ.Elem().Kind() == reflect.Interface { + panic("not support interface type") } - }() + var e any = i + m.typ.Store(efaceOf(&e).typ) + } + m.lock.Unlock() + typ = m.typ.Load() } var f eface - f.typ = m.typ + f.typ = typ if f.typ.IsDirectIface() { f.data = *(*unsafe.Pointer)(unsafe.Pointer(&i)) } else {