]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.14] reflect: handling flagIndir in DeepEqual potential cycles
authorIan Lance Taylor <iant@golang.org>
Wed, 17 Jun 2020 04:57:43 +0000 (21:57 -0700)
committerIan Lance Taylor <iant@golang.org>
Thu, 18 Jun 2020 05:26:27 +0000 (05:26 +0000)
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

src/reflect/all_test.go
src/reflect/deepequal.go

index 5f2f60017481038d4886a666c59e6694a3bc0347..69837c7e341ea4e0e403d17ac6ae6617544c17ae 100644 (file)
@@ -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},
index f2d46165b50fdc44210d86cad614b7372ae19364..8a2bf8b09e23a42274fc70d741605566c765d323 100644 (file)
@@ -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.