aboutsummaryrefslogtreecommitdiff
path: root/cmp/compare.go
diff options
context:
space:
mode:
authorJoe Tsai <joetsai@digital-static.net>2020-06-08 16:37:31 -0700
committerGitHub <noreply@github.com>2020-06-08 16:37:31 -0700
commit11c4583a280337c7ac34c591b4321552981a7cc0 (patch)
tree665edc6d6efa7416baba1daa03dfb819c41da76a /cmp/compare.go
parent1776240f8f841dfa00cb72d811301dbb0298f983 (diff)
downloadgo-cmp-11c4583a280337c7ac34c591b4321552981a7cc0.tar.gz
Avoid leaking implementation details of the exporter (#206)
The current implementation for forcibly exporting fields relies on the reflect.Value.Addr method for the parent struct value, where it copies a non-addressable struct onto to the heap so that it is addressable. However, this action leaks a subtle detail of how the internal implementation works since the accessed field for within a struct is only addressable if and only if the parent struct is also addressable. Modify the implementation to avoid leaking this implementation detail by shallow copying the accessed unexported field to remove any notion of addressability if the parent struct is also unaddressable. Fixes #181
Diffstat (limited to 'cmp/compare.go')
-rw-r--r--cmp/compare.go3
1 files changed, 3 insertions, 0 deletions
diff --git a/cmp/compare.go b/cmp/compare.go
index a58ada5..c82c062 100644
--- a/cmp/compare.go
+++ b/cmp/compare.go
@@ -386,6 +386,7 @@ func sanitizeValue(v reflect.Value, t reflect.Type) reflect.Value {
}
func (s *state) compareStruct(t reflect.Type, vx, vy reflect.Value) {
+ var addr bool
var vax, vay reflect.Value // Addressable versions of vx and vy
var mayForce, mayForceInit bool
@@ -407,6 +408,7 @@ func (s *state) compareStruct(t reflect.Type, vx, vy reflect.Value) {
// For retrieveUnexportedField to work, the parent struct must
// be addressable. Create a new copy of the values if
// necessary to make them addressable.
+ addr = vx.CanAddr() || vy.CanAddr()
vax = makeAddressable(vx)
vay = makeAddressable(vy)
}
@@ -417,6 +419,7 @@ func (s *state) compareStruct(t reflect.Type, vx, vy reflect.Value) {
mayForceInit = true
}
step.mayForce = mayForce
+ step.paddr = addr
step.pvx = vax
step.pvy = vay
step.field = t.Field(i)