diff options
author | Ian Lance Taylor <iant@golang.org> | 2020-06-16 21:57:43 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2020-06-18 05:26:27 +0000 |
commit | e2ecfdf7b478c6b473bac9d9f646f9c37fa17d9b (patch) | |
tree | a3589ccee2c15d37cf5e3b0d10fed2dea1bc59c4 | |
parent | e98cafae04b78f1e994d52ea66d228451c8e6f81 (diff) | |
download | go-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.go | 6 | ||||
-rw-r--r-- | src/reflect/deepequal.go | 16 |
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. |