Close connection on incorrect order of HEADERS and DATA frames.

While the HTTP/3 spec draft does not require this yet, this is the sane thing to
do, and my proposal to change the spec has some support:
https://github.com/quicwg/base-drafts/issues/2858.

This fixes fuzzer-found bug https://crbug.com/978733.

NO_BUG=Bug is https://crbug.com/978733 on Chromium bugtracker.

gfe-relnote: n/a, change in QUIC v99-only code.
PiperOrigin-RevId: 257169271
Change-Id: I10ed66e671f0dc03d6f24694d4c53ba3691e9c51
diff --git a/quic/core/http/quic_spdy_stream.cc b/quic/core/http/quic_spdy_stream.cc
index c625410..96be207 100644
--- a/quic/core/http/quic_spdy_stream.cc
+++ b/quic/core/http/quic_spdy_stream.cc
@@ -760,6 +760,14 @@
 bool QuicSpdyStream::OnDataFrameStart(Http3FrameLengths frame_lengths) {
   DCHECK(
       VersionHasDataFrameHeader(session()->connection()->transport_version()));
+  if (!headers_decompressed_ || trailers_decompressed_) {
+    // TODO(b/124216424): Change error code to HTTP_UNEXPECTED_FRAME.
+    session()->connection()->CloseConnection(
+        QUIC_INVALID_HEADERS_STREAM_DATA, "Unexpected DATA frame received.",
+        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+    return false;
+  }
+
   body_buffer_.OnDataHeader(frame_lengths);
   return true;
 }
@@ -841,6 +849,15 @@
   DCHECK(VersionUsesQpack(spdy_session_->connection()->transport_version()));
   DCHECK(!qpack_decoded_headers_accumulator_);
 
+  if (trailers_decompressed_) {
+    // TODO(b/124216424): Change error code to HTTP_UNEXPECTED_FRAME.
+    session()->connection()->CloseConnection(
+        QUIC_INVALID_HEADERS_STREAM_DATA,
+        "HEADERS frame received after trailing HEADERS.",
+        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+    return false;
+  }
+
   if (headers_decompressed_) {
     trailers_length_ = frame_length;
   } else {