Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/google/protobuf/io/coded_stream.cc
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,10 @@ CodedInputStream::IncrementRecursionDepthAndPushLimit(int byte_limit) {

CodedInputStream::Limit CodedInputStream::ReadLengthAndPushLimit() {
uint32_t length;
return PushLimit(ReadVarint32(&length) ? length : 0);
return PushLimit(ReadVarint32(&length) &&
length <= static_cast<uint32_t>(INT_MAX)
? static_cast<int>(length)
: 0);
}

bool CodedInputStream::DecrementRecursionDepthAndPopLimit(Limit limit) {
Expand Down
15 changes: 15 additions & 0 deletions src/google/protobuf/io/coded_stream_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1576,6 +1576,21 @@ TEST_F(CodedStreamTest, RecursionLimit) {
EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 7
}

TEST_F(CodedStreamTest, ReadLengthAndPushLimitOverflow) {
// Varint encoding of 0x80000000 (2147483648, which overflows signed int32)
uint8_t bytes[] = {0x80, 0x80, 0x80, 0x80, 0x08, 'h', 'e', 'l', 'l', 'o'};
ArrayInputStream input(bytes, sizeof(bytes));
CodedInputStream coded_input(&input);

// When ReadLengthAndPushLimit encounters a length > INT_MAX, it must push limit 0
// so the stream is immediately bounded at 0 remaining bytes instead of overflowing
// into an unconstrained negative limit.
CodedInputStream::Limit limit = coded_input.ReadLengthAndPushLimit();
EXPECT_EQ(0, coded_input.BytesUntilLimit());
EXPECT_TRUE(coded_input.ConsumedEntireMessage());
coded_input.PopLimit(limit);
}


class ReallyBigInputStream : public ZeroCopyInputStream {
public:
Expand Down
Loading