aboutsummaryrefslogtreecommitdiff
path: root/cmp
diff options
context:
space:
mode:
authorJoe Tsai <joetsai@digital-static.net>2017-09-01 14:42:48 -0700
committerGitHub <noreply@github.com>2017-09-01 14:42:48 -0700
commitd5735f74713c51f7450a43d0a98d41ce2c1db3cb (patch)
tree5b1039dcaf523333e2531450b30a4c6fada93679 /cmp
parent8099a9787ce5dc5984ed879a3bda47dc730a8e97 (diff)
downloadgo-cmp-d5735f74713c51f7450a43d0a98d41ce2c1db3cb.tar.gz
Fix panic in sort.go (#39)
Avoid using reflect.Value.Interface to de-duplicate keys since some keys may have source from an unexported field, causing the logic to panic. Instead, just rely on the isLess function, which is already safe to use on unexported values. Fixes #38
Diffstat (limited to 'cmp')
-rw-r--r--cmp/internal/value/sort.go2
-rw-r--r--cmp/internal/value/sort_test.go17
2 files changed, 13 insertions, 6 deletions
diff --git a/cmp/internal/value/sort.go b/cmp/internal/value/sort.go
index ea73cf1..fe8aa27 100644
--- a/cmp/internal/value/sort.go
+++ b/cmp/internal/value/sort.go
@@ -24,7 +24,7 @@ func SortKeys(vs []reflect.Value) []reflect.Value {
// Deduplicate keys (fails for NaNs).
vs2 := vs[:1]
for _, v := range vs[1:] {
- if v.Interface() != vs2[len(vs2)-1].Interface() {
+ if isLess(vs2[len(vs2)-1], v) {
vs2 = append(vs2, v)
}
}
diff --git a/cmp/internal/value/sort_test.go b/cmp/internal/value/sort_test.go
index c5a6bbb..fb86fce 100644
--- a/cmp/internal/value/sort_test.go
+++ b/cmp/internal/value/sort_test.go
@@ -132,15 +132,22 @@ func TestSortKeys(t *testing.T) {
complex(math.NaN(), math.NaN()): true,
},
want: []interface{}{
- math.NaN(), math.NaN(), math.NaN(), math.NaN(),
- complex(math.NaN(), math.NaN()), complex(math.NaN(), math.NaN()),
- complex(math.NaN(), 0), complex(math.NaN(), 0), complex(math.NaN(), 0), complex(math.NaN(), 0),
- complex(0, math.NaN()), complex(0, math.NaN()), complex(0, math.NaN()), complex(0, math.NaN()),
+ math.NaN(),
+ complex(math.NaN(), math.NaN()),
+ complex(math.NaN(), 0),
+ complex(0, math.NaN()),
},
}}
for i, tt := range tests {
- keys := append(reflect.ValueOf(tt.in).MapKeys(), reflect.ValueOf(tt.in).MapKeys()...)
+ // Intentionally pass the map via an unexported field to detect panics.
+ // Unfortunately, we cannot actually test the keys without using unsafe.
+ v := reflect.ValueOf(struct{ x map[interface{}]bool }{tt.in}).Field(0)
+ value.SortKeys(append(v.MapKeys(), v.MapKeys()...))
+
+ // Try again, with keys that have read-write access in reflect.
+ v = reflect.ValueOf(tt.in)
+ keys := append(v.MapKeys(), v.MapKeys()...)
var got []interface{}
for _, k := range value.SortKeys(keys) {
got = append(got, k.Interface())