| Index: net/quic/quic_stream_sequencer.cc
|
| diff --git a/net/quic/quic_stream_sequencer.cc b/net/quic/quic_stream_sequencer.cc
|
| index 81860a3fcc7553b2fcc6abcbc0e9ab8d176fdef3..3a303957c2c694fb6202243706b672963069c34f 100644
|
| --- a/net/quic/quic_stream_sequencer.cc
|
| +++ b/net/quic/quic_stream_sequencer.cc
|
| @@ -11,6 +11,7 @@
|
| #include "base/metrics/sparse_histogram.h"
|
| #include "net/quic/reliable_quic_stream.h"
|
|
|
| +using std::make_pair;
|
| using std::min;
|
| using std::numeric_limits;
|
|
|
| @@ -37,6 +38,12 @@ bool QuicStreamSequencer::OnStreamFrame(const QuicStreamFrame& frame) {
|
| return true;
|
| }
|
|
|
| + if (FrameOverlapsBufferedData(frame)) {
|
| + stream_->CloseConnectionWithDetails(
|
| + QUIC_INVALID_STREAM_FRAME, "Stream frame overlaps with buffered data.");
|
| + return false;
|
| + }
|
| +
|
| QuicStreamOffset byte_offset = frame.offset;
|
| size_t data_len = frame.data.TotalBufferSize();
|
| if (data_len == 0 && !frame.fin) {
|
| @@ -182,8 +189,8 @@ int QuicStreamSequencer::Readv(const struct iovec* iov, size_t iov_len) {
|
| }
|
| // We've finished copying. If we have a partial frame, update it.
|
| if (frame_offset != 0) {
|
| - buffered_frames_.insert(make_pair(it->first + frame_offset,
|
| - it->second.substr(frame_offset)));
|
| + buffered_frames_.insert(
|
| + make_pair(it->first + frame_offset, it->second.substr(frame_offset)));
|
| buffered_frames_.erase(buffered_frames_.begin());
|
| RecordBytesConsumed(frame_offset);
|
| }
|
| @@ -200,6 +207,42 @@ bool QuicStreamSequencer::IsClosed() const {
|
| return num_bytes_consumed_ >= close_offset_;
|
| }
|
|
|
| +bool QuicStreamSequencer::FrameOverlapsBufferedData(
|
| + const QuicStreamFrame& frame) const {
|
| + if (buffered_frames_.empty()) {
|
| + return false;
|
| + }
|
| +
|
| + FrameMap::const_iterator next_frame =
|
| + buffered_frames_.lower_bound(frame.offset);
|
| + // Duplicate frames should have been dropped in IsDuplicate.
|
| + DCHECK(next_frame == buffered_frames_.end() ||
|
| + next_frame->first != frame.offset);
|
| +
|
| + // If there is a buffered frame with a higher starting offset, then we check
|
| + // to see if the new frame runs into the higher frame.
|
| + if (next_frame != buffered_frames_.end() &&
|
| + (frame.offset + frame.data.TotalBufferSize()) > next_frame->first) {
|
| + DVLOG(1) << "New frame overlaps next frame: " << frame.offset << " + "
|
| + << frame.data.TotalBufferSize() << " > " << next_frame->first;
|
| + return true;
|
| + }
|
| +
|
| + // If there is a buffered frame with a lower starting offset, then we check
|
| + // to see if the buffered frame runs into the new frame.
|
| + if (next_frame != buffered_frames_.begin()) {
|
| + FrameMap::const_iterator preceeding_frame = --next_frame;
|
| + QuicStreamOffset offset = preceeding_frame->first;
|
| + uint64 data_length = preceeding_frame->second.length();
|
| + if ((offset + data_length) > frame.offset) {
|
| + DVLOG(1) << "Preceeding frame overlaps new frame: " << offset << " + "
|
| + << data_length << " > " << frame.offset;
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| bool QuicStreamSequencer::IsDuplicate(const QuicStreamFrame& frame) const {
|
| // A frame is duplicate if the frame offset is smaller than our bytes consumed
|
| // or we have stored the frame in our map.
|
|
|