Resize HttpDecoder::buffer_ when buffering data.

Before this change, HttpDecoder::buffer_ was always empty.  A
std::string::reserve() call made sure its storage was large enough, and that
memory was address directly, always beyond the size of the string object.

After this CL, the size of buffer_ reflects the amount of buffered bytes, and
memory beyond its size is never addressed.  The reserve() call is preserved to
avoid reallocation and copy as the buffer grows.

PiperOrigin-RevId: 365076891
Change-Id: If58949fd10fe1741416dab4691faa5c3e728ad8e
diff --git a/quic/core/http/http_decoder.cc b/quic/core/http/http_decoder.cc
index 5377f7c..02b563d 100644
--- a/quic/core/http/http_decoder.cc
+++ b/quic/core/http/http_decoder.cc
@@ -282,10 +282,14 @@
       break;
     }
     case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH): {
+      // TODO(bnc): Avoid buffering if the entire frame is present, and
+      // instead parse directly out of |reader|.
       BufferFramePayload(reader);
       break;
     }
     case static_cast<uint64_t>(HttpFrameType::SETTINGS): {
+      // TODO(bnc): Avoid buffering if the entire frame is present, and
+      // instead parse directly out of |reader|.
       BufferFramePayload(reader);
       break;
     }
@@ -355,10 +359,14 @@
       break;
     }
     case static_cast<uint64_t>(HttpFrameType::GOAWAY): {
+      // TODO(bnc): Avoid buffering if the entire frame is present, and
+      // instead parse directly out of |reader|.
       BufferFramePayload(reader);
       break;
     }
     case static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID): {
+      // TODO(bnc): Avoid buffering if the entire frame is present, and
+      // instead parse directly out of |reader|.
       BufferFramePayload(reader);
       break;
     }
@@ -408,8 +416,11 @@
       break;
     }
     case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH): {
+      // TODO(bnc): Avoid buffering if the entire frame is present, and
+      // instead parse directly out of |reader|.
       CancelPushFrame frame;
-      QuicDataReader reader(buffer_.data(), current_frame_length_);
+      QUICHE_DCHECK_EQ(current_frame_length_, buffer_.size());
+      QuicDataReader reader(buffer_);
       if (!reader.ReadVarInt62(&frame.push_id)) {
         RaiseError(QUIC_HTTP_FRAME_ERROR,
                    "Unable to read CANCEL_PUSH push_id.");
@@ -424,8 +435,11 @@
       break;
     }
     case static_cast<uint64_t>(HttpFrameType::SETTINGS): {
+      // TODO(bnc): Avoid buffering if the entire frame is present, and
+      // instead parse directly out of |reader|.
       SettingsFrame frame;
-      QuicDataReader reader(buffer_.data(), current_frame_length_);
+      QUICHE_DCHECK_EQ(current_frame_length_, buffer_.size());
+      QuicDataReader reader(buffer_);
       if (!ParseSettingsFrame(&reader, &frame)) {
         return false;
       }
@@ -437,7 +451,10 @@
       break;
     }
     case static_cast<uint64_t>(HttpFrameType::GOAWAY): {
-      QuicDataReader reader(buffer_.data(), current_frame_length_);
+      // TODO(bnc): Avoid buffering if the entire frame is present, and
+      // instead parse directly out of |reader|.
+      QUICHE_DCHECK_EQ(current_frame_length_, buffer_.size());
+      QuicDataReader reader(buffer_);
       GoAwayFrame frame;
       if (!reader.ReadVarInt62(&frame.id)) {
         RaiseError(QUIC_HTTP_FRAME_ERROR, "Unable to read GOAWAY ID.");
@@ -451,7 +468,10 @@
       break;
     }
     case static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID): {
-      QuicDataReader reader(buffer_.data(), current_frame_length_);
+      // TODO(bnc): Avoid buffering if the entire frame is present, and
+      // instead parse directly out of |reader|.
+      QUICHE_DCHECK_EQ(current_frame_length_, buffer_.size());
+      QuicDataReader reader(buffer_);
       MaxPushIdFrame frame;
       if (!reader.ReadVarInt62(&frame.push_id)) {
         RaiseError(QUIC_HTTP_FRAME_ERROR,
@@ -470,7 +490,8 @@
       // TODO(bnc): Avoid buffering if the entire frame is present, and
       // instead parse directly out of |reader|.
       PriorityUpdateFrame frame;
-      QuicDataReader reader(buffer_.data(), current_frame_length_);
+      QUICHE_DCHECK_EQ(current_frame_length_, buffer_.size());
+      QuicDataReader reader(buffer_);
       if (!ParsePriorityUpdateFrame(&reader, &frame)) {
         return false;
       }
@@ -481,7 +502,8 @@
       // TODO(bnc): Avoid buffering if the entire frame is present, and
       // instead parse directly out of |reader|.
       PriorityUpdateFrame frame;
-      QuicDataReader reader(buffer_.data(), current_frame_length_);
+      QUICHE_DCHECK_EQ(current_frame_length_, buffer_.size());
+      QuicDataReader reader(buffer_);
       if (!ParseNewPriorityUpdateFrame(&reader, &frame)) {
         return false;
       }
@@ -492,7 +514,8 @@
       // TODO(bnc): Avoid buffering if the entire frame is present, and
       // instead parse directly out of |reader|.
       AcceptChFrame frame;
-      QuicDataReader reader(buffer_.data(), current_frame_length_);
+      QUICHE_DCHECK_EQ(current_frame_length_, buffer_.size());
+      QuicDataReader reader(buffer_);
       if (!ParseAcceptChFrame(&reader, &frame)) {
         return false;
       }
@@ -536,16 +559,21 @@
 
 void HttpDecoder::BufferFramePayload(QuicDataReader* reader) {
   if (current_frame_length_ == remaining_frame_length_) {
-    buffer_.erase(buffer_.size());
+    buffer_.clear();
     buffer_.reserve(current_frame_length_);
   }
+
+  QUICHE_DCHECK_EQ(current_frame_length_ - remaining_frame_length_,
+                   buffer_.size());
   QuicByteCount bytes_to_read = std::min<QuicByteCount>(
       remaining_frame_length_, reader->BytesRemaining());
-  bool success = reader->ReadBytes(
-      &(buffer_[0]) + current_frame_length_ - remaining_frame_length_,
-      bytes_to_read);
-  QUICHE_DCHECK(success);
+  absl::StrAppend(&buffer_, reader->PeekRemainingPayload().substr(
+                                /* pos = */ 0, bytes_to_read));
+  reader->Seek(bytes_to_read);
+
   remaining_frame_length_ -= bytes_to_read;
+  QUICHE_DCHECK_EQ(current_frame_length_ - remaining_frame_length_,
+                   buffer_.size());
 }
 
 void HttpDecoder::BufferFrameLength(QuicDataReader* reader) {