Commit message: None
CVE: CVE-2017-15398
CWE: CWE-119
Vulnerability description: A stack buffer overflow in the QUIC networking stack in Google Chrome prior to 62.0.3202.89 allowed a remote attacker to gain code execution via a malicious server.

Project: Chrome

void QuicClientPromisedInfo::Cancel() {
  client_request_delegate_ = nullptr;
  Reset(QUIC_STREAM_CANCELLED);
}

Project: Chrome

QuicAsyncStatus QuicClientPromisedInfo::FinalValidation() {
  if (!client_request_delegate_->CheckVary(
          *client_request_headers_, *request_headers_, *response_headers_)) {
    Reset(QUIC_PROMISE_VARY_MISMATCH);
    return QUIC_FAILURE;
  }
  QuicSpdyStream* stream = session_->GetPromisedStream(id_);
  if (!stream) {
    QUIC_BUG << "missing promised stream" << id_;
  }
  QuicClientPushPromiseIndex::Delegate* delegate = client_request_delegate_;
  session_->DeletePromised(this);
  if (delegate) {
    delegate->OnRendezvousResult(stream);
  }
  return QUIC_SUCCESS;
}

Project: Chrome

QuicAsyncStatus QuicClientPromisedInfo::HandleClientRequest(
    const SpdyHeaderBlock& request_headers,
    QuicClientPushPromiseIndex::Delegate* delegate) {
  if (session_->IsClosedStream(id_)) {
    session_->DeletePromised(this);
    return QUIC_FAILURE;
  }

  if (is_validating()) {
    return QUIC_FAILURE;
  }

  client_request_delegate_ = delegate;
  client_request_headers_.reset(new SpdyHeaderBlock(request_headers.Clone()));
  if (!response_headers_) {
    return QUIC_PENDING;
  }
  return FinalValidation();
}

Project: Chrome

void QuicClientPromisedInfo::Init() {
  cleanup_alarm_.reset(session_->connection()->alarm_factory()->CreateAlarm(
      new QuicClientPromisedInfo::CleanupAlarm(this)));
  cleanup_alarm_->Set(
      session_->connection()->helper()->GetClock()->ApproximateNow() +
      QuicTime::Delta::FromSeconds(kPushPromiseTimeoutSecs));
}

Project: Chrome

void QuicClientPromisedInfo::CleanupAlarm::OnAlarm() {
  QUIC_DVLOG(1) << "self GC alarm for stream " << promised_->id_;
  promised_->session()->OnPushStreamTimedOut(promised_->id_);
  promised_->Reset(QUIC_PUSH_STREAM_TIMED_OUT);
}

Project: Chrome

void QuicClientPromisedInfo::OnResponseHeaders(const SpdyHeaderBlock& headers) {
  response_headers_.reset(new SpdyHeaderBlock(headers.Clone()));
  if (client_request_delegate_) {
    FinalValidation();
  }
}

Project: Chrome

QuicClientPromisedInfo::QuicClientPromisedInfo(
    QuicSpdyClientSessionBase* session,
    QuicStreamId id,
    string url)
    : session_(session),
      id_(id),
      url_(std::move(url)),
      client_request_delegate_(nullptr) {}

Project: Chrome

void QuicClientPromisedInfo::Reset(QuicRstStreamErrorCode error_code) {
  QuicClientPushPromiseIndex::Delegate* delegate = client_request_delegate_;
  session_->ResetPromised(id_, error_code);
  session_->DeletePromised(this);
  if (delegate) {
    delegate->OnRendezvousResult(nullptr);
  }
}

Project: Chrome

QuicClientPromisedInfo::~QuicClientPromisedInfo() {}

Project: Chrome

  explicit MockQuicSpdyClientSession(
      QuicConnection* connection,
      QuicClientPushPromiseIndex* push_promise_index)
      : QuicSpdyClientSession(
            DefaultQuicConfig(),
            connection,
            QuicServerId("example.com", 443, PRIVACY_MODE_DISABLED),
            &crypto_config_,
            push_promise_index),
        crypto_config_(crypto_test_utils::ProofVerifierForTesting()),
        authorized_(true) {}

Project: Chrome

  void ReceivePromise(QuicStreamId id) {
    auto headers = AsHeaderList(push_promise_);
    stream_->OnPromiseHeaderList(id, headers.uncompressed_header_bytes(),
                                 headers);
  }

Project: Chrome

  void set_authorized(bool authorized) { authorized_ = authorized; }