From: Mauri de Souza Meneguzzo Date: Thu, 20 Jul 2023 23:14:03 +0000 (+0000) Subject: reflect: panic on recv channel close X-Git-Tag: go1.22rc1~1560 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=f2d709b76925696396441274afbc1d178555a8e6;p=gostls13.git reflect: panic on recv channel close It is possible to call reflect.ValueOf(ch).Close() on a recv-only channel, while close(ch) is a compile-time error. Following the same reflect semantics as send and recv this should result in a panic. Fixes #61445 Change-Id: I2a9ee8f45963593a37bd6df4643dd64fb322f9f9 GitHub-Last-Rev: fe2d5e09f5bb5536ac25d1606cf3744fb7a0a4a9 GitHub-Pull-Request: golang/go#61453 Reviewed-on: https://go-review.googlesource.com/c/go/+/511295 Auto-Submit: Ian Lance Taylor TryBot-Result: Gopher Robot Run-TryBot: Ian Lance Taylor Reviewed-by: Bryan Mills Reviewed-by: Ian Lance Taylor --- diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index 31f6416ed9..afd2d2ef79 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -1706,6 +1706,12 @@ func TestChan(t *testing.T) { if i, ok := cv.Recv(); i.Int() != 0 || ok { t.Errorf("after close Recv %d, %t", i.Int(), ok) } + // Closing a read-only channel + shouldPanic("", func() { + c := make(<-chan int, 1) + cv := ValueOf(c) + cv.Close() + }) } // check creation of unbuffered channel diff --git a/src/reflect/value.go b/src/reflect/value.go index 616da6a5c7..127a06e187 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -1187,10 +1187,16 @@ func (v Value) capNonSlice() int { } // Close closes the channel v. -// It panics if v's Kind is not Chan. +// It panics if v's Kind is not Chan or +// v is a receive-only channel. func (v Value) Close() { v.mustBe(Chan) v.mustBeExported() + tt := (*chanType)(unsafe.Pointer(v.typ())) + if ChanDir(tt.Dir)&SendDir == 0 { + panic("reflect: close of receive-only channel") + } + chanclose(v.pointer()) }