in proxygen/lib/http/codec/compress/QPACKDecoder.cpp [55:128]
uint32_t QPACKDecoder::decodePrefix(HPACKDecodeBuffer& dbuf) {
uint64_t requiredInsertCount;
uint64_t wireRIC;
uint64_t maxEntries = getMaxEntries(maxTableSize_);
uint64_t fullRange = 2 * maxEntries;
err_ = dbuf.decodeInteger(wireRIC);
if (err_ != HPACK::DecodeError::NONE) {
LOG(ERROR) << "Decode error decoding requiredInsertCount err_=" << err_;
return 0;
}
if (wireRIC == 0) {
requiredInsertCount = 0;
} else if (maxEntries == 0) {
LOG(ERROR) << "Encoder used dynamic table when not permitted, wireRIC="
<< wireRIC;
err_ = HPACK::DecodeError::INVALID_INDEX;
return 0;
} else {
uint64_t maxValue = table_.getInsertCount() + maxEntries;
uint64_t maxWrapped = (maxValue / fullRange) * fullRange;
requiredInsertCount = maxWrapped + wireRIC - 1;
// If requiredInsertCount exceeds maxValue, the Encoder's value must have
// wrapped one fewer time
if (requiredInsertCount > maxValue) {
if (wireRIC > fullRange || requiredInsertCount < fullRange) {
LOG(ERROR) << "Decode error RIC out of range=" << wireRIC;
err_ = HPACK::DecodeError::INVALID_INDEX;
return 0;
}
requiredInsertCount -= fullRange;
}
}
VLOG(5) << "Decoded requiredInsertCount=" << requiredInsertCount;
uint64_t delta = 0;
if (dbuf.empty()) {
LOG(ERROR) << "Invalid prefix, no delta-base";
err_ = HPACK::DecodeError::BUFFER_UNDERFLOW;
return 0;
}
bool neg = dbuf.peek() & HPACK::Q_DELTA_BASE_NEG;
err_ = dbuf.decodeInteger(HPACK::Q_DELTA_BASE.prefixLength, delta);
if (err_ != HPACK::DecodeError::NONE) {
LOG(ERROR) << "Decode error decoding delta base=" << err_;
return 0;
}
if (neg) {
// delta must be smaller than RIC
if (delta >= requiredInsertCount) {
LOG(ERROR) << "Received invalid delta=" << delta
<< " requiredInsertCount=" << requiredInsertCount;
err_ = HPACK::DecodeError::INVALID_INDEX;
return 0;
}
// The largest table we support is 2^32 - 1 / 32 entries, so
// requiredInsertCount (less any delta, etc) must be < 2^32.
CHECK_LE(requiredInsertCount - delta - 1,
std::numeric_limits<uint32_t>::max());
baseIndex_ = requiredInsertCount - delta - 1;
} else {
// base must be < 2^32
if (delta > std::numeric_limits<uint32_t>::max() ||
requiredInsertCount >=
uint64_t(std::numeric_limits<uint32_t>::max()) - delta) {
LOG(ERROR) << "Invalid delta=" << delta
<< " requiredInsertCount=" << requiredInsertCount;
err_ = HPACK::DecodeError::INVALID_INDEX;
return 0;
}
baseIndex_ = requiredInsertCount + delta;
}
VLOG(5) << "Decoded baseIndex_=" << baseIndex_;
return requiredInsertCount;
}