Skip to content

Commit dda2caa

Browse files
sandarshmeta-codesync[bot]
authored andcommitted
Fix integer overflow in QPACKDecoder.cpp (T259295275)
Reviewed By: afrind Differential Revision: D103181611 fbshipit-source-id: 999c479ac143146850da9050e554948b8495d419
1 parent 33c0160 commit dda2caa

2 files changed

Lines changed: 31 additions & 1 deletion

File tree

proxygen/lib/http/codec/compress/QPACKDecoder.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,19 @@ uint32_t QPACKDecoder::decodePrefix(HPACKDecodeBuffer& dbuf) {
7171
err_ = HPACK::DecodeError::INVALID_INDEX;
7272
return 0;
7373
} else {
74+
if (wireRIC > fullRange) {
75+
LOG(ERROR) << "Decode error RIC out of range=" << wireRIC
76+
<< " fullRange=" << fullRange;
77+
err_ = HPACK::DecodeError::INVALID_INDEX;
78+
return 0;
79+
}
7480
uint64_t maxValue = table_.getInsertCount() + maxEntries;
7581
uint64_t maxWrapped = (maxValue / fullRange) * fullRange;
7682
requiredInsertCount = maxWrapped + wireRIC - 1;
7783
// If requiredInsertCount exceeds maxValue, the Encoder's value must have
7884
// wrapped one fewer time
7985
if (requiredInsertCount > maxValue) {
80-
if (wireRIC > fullRange || requiredInsertCount < fullRange) {
86+
if (requiredInsertCount < fullRange) {
8187
LOG(ERROR) << "Decode error RIC out of range=" << wireRIC;
8288
err_ = HPACK::DecodeError::INVALID_INDEX;
8389
return 0;

proxygen/lib/http/codec/compress/test/QPACKContextTests.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
#include <folly/Format.h>
1111
#include <folly/portability/GTest.h>
1212
#include <glog/logging.h>
13+
#include <limits>
1314
#include <memory>
15+
#include <proxygen/lib/http/codec/compress/HPACKEncodeBuffer.h>
1416
#include <proxygen/lib/http/codec/compress/Logging.h>
1517
#include <proxygen/lib/http/codec/compress/QPACKDecoder.h>
1618
#include <proxygen/lib/http/codec/compress/QPACKEncoder.h>
@@ -858,6 +860,28 @@ void checkQError(QPACKDecoder& decoder,
858860
EXPECT_EQ(cb->error, err);
859861
}
860862

863+
TEST(QPACKContextTests, RejectsOverflowingRequiredInsertCount) {
864+
QPACKDecoder decoder;
865+
HPACKEncodeBuffer insertStream(128, false);
866+
const uint32_t maxEntries = HPACK::kTableSize / HPACKHeader::kMinLength;
867+
// Prime insertCount so RIC reconstruction uses a non-zero maxWrapped value.
868+
for (uint32_t i = 0; i < maxEntries; i++) {
869+
insertStream.encodeLiteral(HPACK::Q_INSERT_NO_NAME_REF.code,
870+
HPACK::Q_INSERT_NO_NAME_REF.prefixLength,
871+
folly::to<string>("x-overflow-", i));
872+
insertStream.encodeLiteral("v");
873+
}
874+
EXPECT_EQ(decoder.decodeEncoderStream(insertStream.release()),
875+
HPACK::DecodeError::NONE);
876+
877+
HPACKEncodeBuffer headerBlock(128, false);
878+
// This value used to overflow maxWrapped + wireRIC - 1 before validation.
879+
headerBlock.encodeInteger(std::numeric_limits<uint64_t>::max() - 154);
880+
headerBlock.encodeInteger(0, HPACK::Q_DELTA_BASE);
881+
checkQError(
882+
decoder, headerBlock.release(), HPACK::DecodeError::INVALID_INDEX);
883+
}
884+
861885
TEST(QPACKContextTests, DecodeErrors) {
862886
QPACKDecoder decoder(128);
863887
unique_ptr<IOBuf> buf = IOBuf::create(128);

0 commit comments

Comments
 (0)