reflect: update Select to panic early on excessive input cases

The runtime implementation of select has an upper limit on the number of
select cases that are supported in order to maintain low stack memory
usage. Rather than support an arbitrary number of select cases, we've
opted to panic early with a useful message pointing the user directly
at the problem.

Fixes #37350

Change-Id: Id129ba281ae120387e681ef96be8adcf89725840
Reviewed-on: https://go-review.googlesource.com/c/go/+/220583
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Milan Patel 2020-02-23 15:27:05 -05:00 committed by Ian Lance Taylor
parent 821b799482
commit 7802b55176
3 changed files with 38 additions and 2 deletions

View file

@ -1651,6 +1651,35 @@ func TestSelect(t *testing.T) {
}
}
func TestSelectMaxCases(t *testing.T) {
var sCases []SelectCase
channel := make(chan int)
close(channel)
for i := 0; i < 65536; i++ {
sCases = append(sCases, SelectCase{
Dir: SelectRecv,
Chan: ValueOf(channel),
})
}
// Should not panic
_, _, _ = Select(sCases)
sCases = append(sCases, SelectCase{
Dir: SelectRecv,
Chan: ValueOf(channel),
})
defer func() {
if err := recover(); err != nil {
if err.(string) != "reflect.Select: too many cases (max 65536)" {
t.Fatalf("unexpected error from select call with greater than max supported cases")
}
} else {
t.Fatalf("expected select call to panic with greater than max supported cases")
}
}()
// Should panic
_, _, _ = Select(sCases)
}
// selectWatch and the selectWatcher are a watchdog mechanism for running Select.
// If the selectWatcher notices that the select has been blocked for >1 second, it prints
// an error describing the select and panics the entire test binary.