http2: don't panic when ServeConn is passed a nil options

Fixes golang/go#75286

Change-Id: I91e6a0a61234c81f809b74151946dddde9099078
Reviewed-on: https://go-review.googlesource.com/c/net/+/700999
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Nicholas Husin <nsh@golang.org>
Reviewed-by: Nicholas Husin <husin@google.com>
Auto-Submit: Nicholas Husin <nsh@golang.org>
diff --git a/http2/http2_test.go b/http2/http2_test.go
index d263c1b..cd86fa8 100644
--- a/http2/http2_test.go
+++ b/http2/http2_test.go
@@ -287,7 +287,7 @@
 }
 
 // setForTest sets *p = v, and restores its original value in t.Cleanup.
-func setForTest[T any](t *testing.T, p *T, v T) {
+func setForTest[T any](t testing.TB, p *T, v T) {
 	orig := *p
 	t.Cleanup(func() {
 		*p = orig
diff --git a/http2/server.go b/http2/server.go
index 7c5c466..3d41353 100644
--- a/http2/server.go
+++ b/http2/server.go
@@ -390,6 +390,9 @@
 //
 // The opts parameter is optional. If nil, default values are used.
 func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
+	if opts == nil {
+		opts = &ServeConnOpts{}
+	}
 	s.serveConn(c, opts, nil)
 }
 
diff --git a/http2/server_test.go b/http2/server_test.go
index 9b028de..a60e717 100644
--- a/http2/server_test.go
+++ b/http2/server_test.go
@@ -3266,26 +3266,47 @@
 func (c *issue53Conn) SetReadDeadline(t time.Time) error  { return nil }
 func (c *issue53Conn) SetWriteDeadline(t time.Time) error { return nil }
 
+// TestServeConnNilOpts ensures that Server.ServeConn(conn, nil) works.
+//
 // golang.org/issue/33839
-func TestServeConnOptsNilReceiverBehavior(t *testing.T) {
-	synctestTest(t, testServeConnOptsNilReceiverBehavior)
-}
-func testServeConnOptsNilReceiverBehavior(t testing.TB) {
-	defer func() {
-		if r := recover(); r != nil {
-			t.Errorf("got a panic that should not happen: %v", r)
-		}
-	}()
+func TestServeConnNilOpts(t *testing.T) { synctestTest(t, testServeConnNilOpts) }
+func testServeConnNilOpts(t testing.TB) {
+	// A nil ServeConnOpts uses http.DefaultServeMux as the handler.
+	var gotRequest string
+	var mux http.ServeMux
+	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+		gotRequest = r.URL.Path
+	})
+	setForTest(t, &http.DefaultServeMux, &mux)
 
-	var o *ServeConnOpts
-	if o.context() == nil {
-		t.Error("o.context should not return nil")
-	}
-	if o.baseConfig() == nil {
-		t.Error("o.baseConfig should not return nil")
-	}
-	if o.handler() == nil {
-		t.Error("o.handler should not return nil")
+	srvConn, cliConn := net.Pipe()
+	defer srvConn.Close()
+	defer cliConn.Close()
+
+	s2 := &Server{}
+	go s2.ServeConn(srvConn, nil)
+
+	fr := NewFramer(cliConn, cliConn)
+	io.WriteString(cliConn, ClientPreface)
+	fr.WriteSettings()
+	fr.WriteSettingsAck()
+	var henc hpackEncoder
+	const reqPath = "/request"
+	fr.WriteHeaders(HeadersFrameParam{
+		StreamID: 1,
+		BlockFragment: henc.encodeHeaderRaw(t,
+			":method", "GET",
+			":path", reqPath,
+			":scheme", "https",
+			":authority", "foo.com",
+		),
+		EndStream:  true,
+		EndHeaders: true,
+	})
+
+	synctest.Wait()
+	if got, want := gotRequest, reqPath; got != want {
+		t.Errorf("got request: %q, want %q", got, want)
 	}
 }