summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Neil <dneil@google.com>2024-02-26 12:25:37 -0800
committerDamien Neil <dneil@google.com>2024-03-11 21:02:17 +0000
commit12ddef72728707026a3d9adbbc28affa76faf688 (patch)
tree71964ef63b69c631e9c3d8b91900b78e9804e767
parentd600ae05799943851536e26ab37ee23294912c3d (diff)
downloadgolang-x-net-12ddef72728707026a3d9adbbc28affa76faf688.tar.gz
http2: reject DATA frames after 1xx and before final headers
When checking to see if a DATA frame can be accepted, check to see if we have received a non-1xx header, not whether we have received any header. Fixes golang/go#65927 Change-Id: Id4fae1862de6179f8fc95e02dec7d4c47a7640e1 Reviewed-on: https://go-review.googlesource.com/c/net/+/567175 Reviewed-by: Jonathan Amsterdam <jba@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
-rw-r--r--http2/transport.go2
-rw-r--r--http2/transport_test.go29
2 files changed, 30 insertions, 1 deletions
diff --git a/http2/transport.go b/http2/transport.go
index 04db292..44845ba 100644
--- a/http2/transport.go
+++ b/http2/transport.go
@@ -2787,7 +2787,7 @@ func (rl *clientConnReadLoop) processData(f *DataFrame) error {
})
return nil
}
- if !cs.firstByte {
+ if !cs.pastHeaders {
cc.logf("protocol error: received DATA before a HEADERS frame")
rl.endStreamError(cs, StreamError{
StreamID: f.StreamID,
diff --git a/http2/transport_test.go b/http2/transport_test.go
index f889cd1..836d455 100644
--- a/http2/transport_test.go
+++ b/http2/transport_test.go
@@ -6254,3 +6254,32 @@ func TestDialRaceResumesDial(t *testing.T) {
case <-successCh:
}
}
+
+func TestTransportDataAfter1xxHeader(t *testing.T) {
+ // Discard logger output to avoid spamming stderr.
+ log.SetOutput(io.Discard)
+ defer log.SetOutput(os.Stderr)
+
+ // https://go.dev/issue/65927 - server sends a 1xx response, followed by a DATA frame.
+ tc := newTestClientConn(t)
+ tc.greet()
+
+ req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
+ rt := tc.roundTrip(req)
+
+ tc.wantFrameType(FrameHeaders)
+ tc.writeHeaders(HeadersFrameParam{
+ StreamID: rt.streamID(),
+ EndHeaders: true,
+ EndStream: false,
+ BlockFragment: tc.makeHeaderBlockFragment(
+ ":status", "100",
+ ),
+ })
+ tc.writeData(rt.streamID(), true, []byte{0})
+ err := rt.err()
+ if err, ok := err.(StreamError); !ok || err.Code != ErrCodeProtocol {
+ t.Errorf("RoundTrip error: %v; want ErrCodeProtocol", err)
+ }
+ tc.wantFrameType(FrameRSTStream)
+}