Skip to content

Commit 085529b

Browse files
cuonglmrandall77
authored andcommitted
cmd/compile: fix wrong unsafe.Offsetof evaluation inside generic function
For instantiated generic functions, all implicit dot operations are resolved. Thus unsafe.Offsetof may calculating the offset against the wrong base selector. To fix it, we must remove any implicit dot operations to find the first non-implicit one, which is the right base selector for calculating the offset. Fixes #53137 Change-Id: I38504067ce0f274615b306edc8f7d7933bdb631a Reviewed-on: https://go-review.googlesource.com/c/go/+/409355 Run-TryBot: Cuong Manh Le <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]> Reviewed-by: Keith Randall <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Keith Randall <[email protected]>
1 parent cfd202c commit 085529b

File tree

2 files changed

+44
-0
lines changed

2 files changed

+44
-0
lines changed

src/cmd/compile/internal/typecheck/const.go

+12
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,18 @@ func evalunsafe(n ir.Node) int64 {
805805
sel.X = Expr(sel.X)
806806
sbase := sel.X
807807

808+
// Implicit dot may already be resolved for instantiating generic function. So we
809+
// need to remove any implicit dot until we reach the first non-implicit one, it's
810+
// the right base selector. See issue #53137.
811+
var clobberBase func(n ir.Node) ir.Node
812+
clobberBase = func(n ir.Node) ir.Node {
813+
if sel, ok := n.(*ir.SelectorExpr); ok && sel.Implicit() {
814+
return clobberBase(sel.X)
815+
}
816+
return n
817+
}
818+
sbase = clobberBase(sbase)
819+
808820
tsel := Expr(sel)
809821
n.X = tsel
810822
if tsel.Type() == nil {

test/fixedbugs/issue53137.go

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// run
2+
3+
// Copyright 2022 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
package main
8+
9+
import (
10+
"unsafe"
11+
)
12+
13+
type Embedded struct {
14+
B int
15+
}
16+
17+
type S[K any] struct {
18+
A K
19+
Embedded
20+
}
21+
22+
func showOffsets[K any](d *S[K]) {
23+
o1 := unsafe.Offsetof(d.B)
24+
o2 := unsafe.Offsetof(d.Embedded)
25+
if o1 != o2 {
26+
panic("offset mismatch")
27+
}
28+
}
29+
30+
func main() {
31+
showOffsets(new(S[int]))
32+
}

0 commit comments

Comments
 (0)