// Copyright 2016 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "net/third_party/http2/decoder/frame_decoder_state.h" namespace http2 { DecodeStatus FrameDecoderState::ReadPadLength(DecodeBuffer* db, bool report_pad_length) { DVLOG(2) << "ReadPadLength db->Remaining=" << db->Remaining() << "; payload_length=" << frame_header().payload_length; DCHECK(IsPaddable()); DCHECK(frame_header().IsPadded()); // Pad Length is always at the start of the frame, so remaining_payload_ // should equal payload_length at this point. const uint32_t total_payload = frame_header().payload_length; DCHECK_EQ(total_payload, remaining_payload_); DCHECK_EQ(0u, remaining_padding_); if (db->HasData()) { const uint32_t pad_length = db->DecodeUInt8(); const uint32_t total_padding = pad_length + 1; if (total_padding <= total_payload) { remaining_padding_ = pad_length; remaining_payload_ = total_payload - total_padding; if (report_pad_length) { listener()->OnPadLength(pad_length); } return DecodeStatus::kDecodeDone; } const uint32_t missing_length = total_padding - total_payload; // To allow for the possibility of recovery, record the number of // remaining bytes of the frame's payload (invalid though it is) // in remaining_payload_. remaining_payload_ = total_payload - 1; // 1 for sizeof(Pad Length). remaining_padding_ = 0; listener()->OnPaddingTooLong(frame_header(), missing_length); return DecodeStatus::kDecodeError; } if (total_payload == 0) { remaining_payload_ = 0; remaining_padding_ = 0; listener()->OnPaddingTooLong(frame_header(), 1); return DecodeStatus::kDecodeError; } // Need to wait for another buffer. return DecodeStatus::kDecodeInProgress; } bool FrameDecoderState::SkipPadding(DecodeBuffer* db) { DVLOG(2) << "SkipPadding remaining_padding_=" << remaining_padding_ << ", db->Remaining=" << db->Remaining() << ", header: " << frame_header(); DCHECK_EQ(remaining_payload_, 0u); DCHECK(IsPaddable()) << "header: " << frame_header(); DCHECK_GE(remaining_padding_, 0u); DCHECK(remaining_padding_ == 0 || frame_header().IsPadded()) << "remaining_padding_=" << remaining_padding_ << ", header: " << frame_header(); const size_t avail = AvailablePadding(db); if (avail > 0) { listener()->OnPadding(db->cursor(), avail); db->AdvanceCursor(avail); remaining_padding_ -= avail; } return remaining_padding_ == 0; } DecodeStatus FrameDecoderState::ReportFrameSizeError() { DVLOG(2) << "FrameDecoderState::ReportFrameSizeError: " << " remaining_payload_=" << remaining_payload_ << "; remaining_padding_=" << remaining_padding_ << ", header: " << frame_header(); listener()->OnFrameSizeError(frame_header()); return DecodeStatus::kDecodeError; } } // namespace http2