aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2020-06-16 21:57:43 -0700
committerIan Lance Taylor <iant@golang.org>2020-06-18 05:26:27 +0000
commite2ecfdf7b478c6b473bac9d9f646f9c37fa17d9b (patch)
treea3589ccee2c15d37cf5e3b0d10fed2dea1bc59c4
parente98cafae04b78f1e994d52ea66d228451c8e6f81 (diff)
downloadgo-e2ecfdf7b478c6b473bac9d9f646f9c37fa17d9b.tar.gz
go-e2ecfdf7b478c6b473bac9d9f646f9c37fa17d9b.zip
[release-branch.go1.14] reflect: handling flagIndir in DeepEqual potential cycles
For #39607 Fixes #39636 Change-Id: Ia7e597e0da8a193a25382cc633a1c6080b4f7cbf Reviewed-on: https://go-review.googlesource.com/c/go/+/238361 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org> (cherry picked from commit d872bbcfec29f2585ed8144fba6262d4228619cf) Reviewed-on: https://go-review.googlesource.com/c/go/+/238626
-rw-r--r--src/reflect/all_test.go6
-rw-r--r--src/reflect/deepequal.go16
2 files changed, 20 insertions, 2 deletions
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go
index 5f2f600174..69837c7e34 100644
--- a/src/reflect/all_test.go
+++ b/src/reflect/all_test.go
@@ -789,6 +789,11 @@ var loop1, loop2 Loop
var loopy1, loopy2 Loopy
var cycleMap1, cycleMap2, cycleMap3 map[string]interface{}
+type structWithSelfPtr struct {
+ p *structWithSelfPtr
+ s string
+}
+
func init() {
loop1 = &loop2
loop2 = &loop1
@@ -845,6 +850,7 @@ var deepEqualTests = []DeepEqualTest{
{[]float64{math.NaN()}, self{}, true},
{map[float64]float64{math.NaN(): 1}, map[float64]float64{1: 2}, false},
{map[float64]float64{math.NaN(): 1}, self{}, true},
+ {&structWithSelfPtr{p: &structWithSelfPtr{s: "a"}}, &structWithSelfPtr{p: &structWithSelfPtr{s: "b"}}, false},
// Nil vs empty: not the same.
{[]int{}, []int(nil), false},
diff --git a/src/reflect/deepequal.go b/src/reflect/deepequal.go
index f2d46165b5..8a2bf8b09e 100644
--- a/src/reflect/deepequal.go
+++ b/src/reflect/deepequal.go
@@ -45,8 +45,20 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool, depth int) bool {
}
if hard(v1, v2) {
- addr1 := v1.ptr
- addr2 := v2.ptr
+ // For a Ptr or Map value, we need to check flagIndir,
+ // which we do by calling the pointer method.
+ // For Slice or Interface, flagIndir is always set,
+ // and using v.ptr suffices.
+ ptrval := func(v Value) unsafe.Pointer {
+ switch v.Kind() {
+ case Ptr, Map:
+ return v.pointer()
+ default:
+ return v.ptr
+ }
+ }
+ addr1 := ptrval(v1)
+ addr2 := ptrval(v2)
if uintptr(addr1) > uintptr(addr2) {
// Canonicalize order to reduce number of entries in visited.
// Assumes non-moving garbage collector.