In QUIC, when creator is consuming data in fast path, close connection if stream data is sent in the wrong encryption level. Protected by gfe2_reloadable_flag_quic_check_encryption_level_in_fast_path.

PiperOrigin-RevId: 324666221
Change-Id: I370f76efb1127636e66215fc0fb8dc8b60879988
diff --git a/quic/core/quic_packet_creator.cc b/quic/core/quic_packet_creator.cc
index 109042f..f842538 100644
--- a/quic/core/quic_packet_creator.cc
+++ b/quic/core/quic_packet_creator.cc
@@ -1324,6 +1324,13 @@
     bool fin,
     size_t total_bytes_consumed) {
   DCHECK(!QuicUtils::IsCryptoStreamId(transport_version(), id));
+  if (GetQuicReloadableFlag(quic_check_encryption_level_in_fast_path)) {
+    QUIC_RELOADABLE_FLAG_COUNT(quic_check_encryption_level_in_fast_path);
+    if (AttemptingToSendUnencryptedStreamData()) {
+      return QuicConsumedData(total_bytes_consumed,
+                              fin && (total_bytes_consumed == write_length));
+    }
+  }
 
   while (total_bytes_consumed < write_length &&
          delegate_->ShouldGeneratePacket(HAS_RETRANSMITTABLE_DATA,
@@ -1612,14 +1619,7 @@
   if (frame.type == STREAM_FRAME &&
       !QuicUtils::IsCryptoStreamId(framer_->transport_version(),
                                    frame.stream_frame.stream_id) &&
-      (packet_.encryption_level == ENCRYPTION_INITIAL ||
-       packet_.encryption_level == ENCRYPTION_HANDSHAKE)) {
-    const std::string error_details =
-        quiche::QuicheStrCat("Cannot send stream data with level: ",
-                             EncryptionLevelToString(packet_.encryption_level));
-    QUIC_BUG << error_details;
-    delegate_->OnUnrecoverableError(
-        QUIC_ATTEMPT_TO_SEND_UNENCRYPTED_STREAM_DATA, error_details);
+      AttemptingToSendUnencryptedStreamData()) {
     return false;
   }
 
@@ -1949,6 +1949,20 @@
   return largest_payload;
 }
 
+bool QuicPacketCreator::AttemptingToSendUnencryptedStreamData() {
+  if (packet_.encryption_level == ENCRYPTION_ZERO_RTT ||
+      packet_.encryption_level == ENCRYPTION_FORWARD_SECURE) {
+    return false;
+  }
+  const std::string error_details =
+      quiche::QuicheStrCat("Cannot send stream data with level: ",
+                           EncryptionLevelToString(packet_.encryption_level));
+  QUIC_BUG << error_details;
+  delegate_->OnUnrecoverableError(QUIC_ATTEMPT_TO_SEND_UNENCRYPTED_STREAM_DATA,
+                                  error_details);
+  return true;
+}
+
 bool QuicPacketCreator::HasIetfLongHeader() const {
   return VersionHasIetfInvariantHeader(framer_->transport_version()) &&
          packet_.encryption_level < ENCRYPTION_FORWARD_SECURE;
diff --git a/quic/core/quic_packet_creator.h b/quic/core/quic_packet_creator.h
index 8db087a..a225793 100644
--- a/quic/core/quic_packet_creator.h
+++ b/quic/core/quic_packet_creator.h
@@ -571,6 +571,9 @@
   // packet size required for header protection.
   void MaybeAddExtraPaddingForHeaderProtection();
 
+  // Returns true and close connection if it attempts to send unencrypted data.
+  bool AttemptingToSendUnencryptedStreamData();
+
   // Does not own these delegates or the framer.
   DelegateInterface* delegate_;
   DebugDelegate* debug_delegate_;
diff --git a/quic/core/quic_packet_creator_test.cc b/quic/core/quic_packet_creator_test.cc
index 7943cee..60703fb 100644
--- a/quic/core/quic_packet_creator_test.cc
+++ b/quic/core/quic_packet_creator_test.cc
@@ -2593,6 +2593,24 @@
   delete rst_frame;
 }
 
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+       WrongEncryptionLevelForStreamDataFastPath) {
+  if (!GetQuicReloadableFlag(quic_check_encryption_level_in_fast_path)) {
+    return;
+  }
+  creator_.set_encryption_level(ENCRYPTION_HANDSHAKE);
+  delegate_.SetCanWriteAnything();
+  // Create a 10000 byte IOVector.
+  CreateData(10000);
+  EXPECT_CALL(delegate_, OnSerializedPacket(_)).Times(0);
+  EXPECT_CALL(delegate_, OnUnrecoverableError(_, _));
+  EXPECT_QUIC_BUG(creator_.ConsumeDataFastPath(
+                      QuicUtils::GetFirstBidirectionalStreamId(
+                          framer_.transport_version(), Perspective::IS_CLIENT),
+                      &iov_, 1u, iov_.iov_len, 0, true),
+                  "");
+}
+
 TEST_F(QuicPacketCreatorMultiplePacketsTest, AddControlFrame_OnlyAckWritable) {
   delegate_.SetCanWriteOnlyNonRetransmittable();