aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunyang Shao <shaojunyang@google.com>2026-03-12 21:36:33 +0000
committerGopher Robot <gobot@golang.org>2026-04-07 12:14:04 -0700
commit3a4577a2687ad46d2a00305ddb68733283ea0720 (patch)
treec5708800a5e49313c96a3265a2d8074178f4f9b4
parentceb4da6626ce94d75b2aefd0f24c6d0fd74f45f9 (diff)
downloadgo-3a4577a2687ad46d2a00305ddb68733283ea0720.tar.xz
[release-branch.go1.26] cmd/compile: fix mem access overlap detection
When a no-op interface conversion is wrapped around the rhs of an assignment, the memory overlap detection logic in the compiler failed to peel down conversion to see the actual pointer, causing an incorrect no-overlapping determination. Thanks to Jakub Ciolek for reporting this issue. Fixes #78371 Fixes CVE-2026-27144 Change-Id: I55ff0806b099e1447bdbfba7fde6c6597db5d65c Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3780 Reviewed-by: Damien Neil <dneil@google.com> Reviewed-by: Neal Patel <nealpatel@google.com> Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/4001 Commit-Queue: Damien Neil <dneil@google.com> Reviewed-on: https://go-review.googlesource.com/c/go/+/763545 TryBot-Bypass: Gopher Robot <gobot@golang.org> Reviewed-by: Junyang Shao <shaojunyang@google.com> Reviewed-by: David Chase <drchase@google.com> Auto-Submit: Gopher Robot <gobot@golang.org>
-rw-r--r--src/cmd/compile/internal/ssagen/ssa.go20
-rw-r--r--src/cmd/compile/internal/test/memoverlap_test.go41
2 files changed, 55 insertions, 6 deletions
diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go
index 849781c9ee..3da43e715e 100644
--- a/src/cmd/compile/internal/ssagen/ssa.go
+++ b/src/cmd/compile/internal/ssagen/ssa.go
@@ -1653,6 +1653,16 @@ func (s *state) stmtList(l ir.Nodes) {
}
}
+func peelConvNop(n ir.Node) ir.Node {
+ if n == nil {
+ return n
+ }
+ for n.Op() == ir.OCONVNOP {
+ n = n.(*ir.ConvExpr).X
+ }
+ return n
+}
+
// stmt converts the statement n to SSA and adds it to s.
func (s *state) stmt(n ir.Node) {
s.pushLine(n.Pos())
@@ -1828,12 +1838,10 @@ func (s *state) stmt(n ir.Node) {
// arrays referenced are strictly smaller parts of the same base array.
// If one side of the assignment is a full array, then partial overlap
// can't happen. (The arrays are either disjoint or identical.)
- mayOverlap := n.X.Op() == ir.ODEREF && (n.Y != nil && n.Y.Op() == ir.ODEREF)
- if n.Y != nil && n.Y.Op() == ir.ODEREF {
- p := n.Y.(*ir.StarExpr).X
- for p.Op() == ir.OCONVNOP {
- p = p.(*ir.ConvExpr).X
- }
+ ny := peelConvNop(n.Y)
+ mayOverlap := n.X.Op() == ir.ODEREF && (n.Y != nil && ny.Op() == ir.ODEREF)
+ if ny != nil && ny.Op() == ir.ODEREF {
+ p := peelConvNop(ny.(*ir.StarExpr).X)
if p.Op() == ir.OSPTR && p.(*ir.UnaryExpr).X.Type().IsString() {
// Pointer fields of strings point to unmodifiable memory.
// That memory can't overlap with the memory being written.
diff --git a/src/cmd/compile/internal/test/memoverlap_test.go b/src/cmd/compile/internal/test/memoverlap_test.go
new file mode 100644
index 0000000000..c53288e6bb
--- /dev/null
+++ b/src/cmd/compile/internal/test/memoverlap_test.go
@@ -0,0 +1,41 @@
+// Copyright 2026 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package test
+
+import "testing"
+
+const arrFooSize = 96
+
+type arrFoo [arrFooSize]int
+
+//go:noinline
+func badCopy(dst, src []int) {
+ p := (*[arrFooSize]int)(dst[:arrFooSize])
+ q := (*[arrFooSize]int)(src[:arrFooSize])
+ *p = arrFoo(*q)
+}
+
+//go:noinline
+func goodCopy(dst, src []int) {
+ p := (*[arrFooSize]int)(dst[:arrFooSize])
+ q := (*[arrFooSize]int)(src[:arrFooSize])
+ *p = *q
+}
+
+func TestOverlapedMoveWithNoopIConv(t *testing.T) {
+ h1 := make([]int, arrFooSize+1)
+ h2 := make([]int, arrFooSize+1)
+ for i := range arrFooSize + 1 {
+ h1[i] = i
+ h2[i] = i
+ }
+ badCopy(h1[1:], h1[:arrFooSize])
+ goodCopy(h2[1:], h2[:arrFooSize])
+ for i := range arrFooSize + 1 {
+ if h1[i] != h2[i] {
+ t.Errorf("h1 and h2 differ at index %d, expect them to be the same", i)
+ }
+ }
+}