mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-29 20:52:08 -05:00
tpl: Fix panic in pairList.Less
While sorting on data sources with missing fields, a panic can occur in pairList.Less if `Interface()` is called on a invalid `reflect.Value`. This commit detects an invalid Value and replacing it with a zero value for the comparison.
This commit is contained in:
parent
7d5c9fbf44
commit
d15fda5000
2 changed files with 33 additions and 1 deletions
|
@ -1054,7 +1054,24 @@ type pairList struct {
|
||||||
func (p pairList) Swap(i, j int) { p.Pairs[i], p.Pairs[j] = p.Pairs[j], p.Pairs[i] }
|
func (p pairList) Swap(i, j int) { p.Pairs[i], p.Pairs[j] = p.Pairs[j], p.Pairs[i] }
|
||||||
func (p pairList) Len() int { return len(p.Pairs) }
|
func (p pairList) Len() int { return len(p.Pairs) }
|
||||||
func (p pairList) Less(i, j int) bool {
|
func (p pairList) Less(i, j int) bool {
|
||||||
return lt(p.Pairs[i].SortByValue.Interface(), p.Pairs[j].SortByValue.Interface())
|
iv := p.Pairs[i].SortByValue
|
||||||
|
jv := p.Pairs[j].SortByValue
|
||||||
|
|
||||||
|
if iv.IsValid() {
|
||||||
|
if jv.IsValid() {
|
||||||
|
// can only call Interface() on valid reflect Values
|
||||||
|
return lt(iv.Interface(), jv.Interface())
|
||||||
|
}
|
||||||
|
// if j is invalid, test i against i's zero value
|
||||||
|
return lt(iv.Interface(), reflect.Zero(iv.Type()))
|
||||||
|
}
|
||||||
|
|
||||||
|
if jv.IsValid() {
|
||||||
|
// if i is invalid, test j against j's zero value
|
||||||
|
return lt(reflect.Zero(jv.Type()), jv.Interface())
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// sorts a pairList and returns a slice of sorted values
|
// sorts a pairList and returns a slice of sorted values
|
||||||
|
|
|
@ -1535,6 +1535,21 @@ func TestSort(t *testing.T) {
|
||||||
"asc",
|
"asc",
|
||||||
[]map[string]mid{{"foo": mid{Tst: TstX{A: "a", B: "b"}}}, {"foo": mid{Tst: TstX{A: "c", B: "d"}}}, {"foo": mid{Tst: TstX{A: "e", B: "f"}}}},
|
[]map[string]mid{{"foo": mid{Tst: TstX{A: "a", B: "b"}}}, {"foo": mid{Tst: TstX{A: "c", B: "d"}}}, {"foo": mid{Tst: TstX{A: "e", B: "f"}}}},
|
||||||
},
|
},
|
||||||
|
// interface slice with missing elements
|
||||||
|
{
|
||||||
|
[]interface{}{
|
||||||
|
map[interface{}]interface{}{"Title": "Foo", "Weight": 10},
|
||||||
|
map[interface{}]interface{}{"Title": "Bar"},
|
||||||
|
map[interface{}]interface{}{"Title": "Zap", "Weight": 5},
|
||||||
|
},
|
||||||
|
"Weight",
|
||||||
|
"asc",
|
||||||
|
[]interface{}{
|
||||||
|
map[interface{}]interface{}{"Title": "Bar"},
|
||||||
|
map[interface{}]interface{}{"Title": "Zap", "Weight": 5},
|
||||||
|
map[interface{}]interface{}{"Title": "Foo", "Weight": 10},
|
||||||
|
},
|
||||||
|
},
|
||||||
// test error cases
|
// test error cases
|
||||||
{(*[]TstX)(nil), nil, "asc", false},
|
{(*[]TstX)(nil), nil, "asc", false},
|
||||||
{TstX{A: "a", B: "b"}, nil, "asc", false},
|
{TstX{A: "a", B: "b"}, nil, "asc", false},
|
||||||
|
|
Loading…
Reference in a new issue