Skip to content

Commit

Permalink
Fix an issue where the ByteSource path (used for parsing std::string)
Browse files Browse the repository at this point in the history
would incorrectly accept some invalid varints that the other path would not,
causing potential CHECK-failures if the unit test were run with
--write_uncompressed and a corrupted input file.

Found by the afl fuzzer.
  • Loading branch information
sesse committed Jan 4, 2016
1 parent ef5598a commit 7525a16
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 1 deletion.
2 changes: 2 additions & 0 deletions snappy-test.h
Expand Up @@ -196,6 +196,7 @@ void Test_Snappy_RandomData();
void Test_Snappy_FourByteOffset();
void Test_SnappyCorruption_TruncatedVarint();
void Test_SnappyCorruption_UnterminatedVarint();
void Test_SnappyCorruption_OverflowingVarint();
void Test_Snappy_ReadPastEndOfBuffer();
void Test_Snappy_FindMatchLength();
void Test_Snappy_FindMatchLengthRandom();
Expand Down Expand Up @@ -500,6 +501,7 @@ static inline int RUN_ALL_TESTS() {
snappy::Test_Snappy_FourByteOffset();
snappy::Test_SnappyCorruption_TruncatedVarint();
snappy::Test_SnappyCorruption_UnterminatedVarint();
snappy::Test_SnappyCorruption_OverflowingVarint();
snappy::Test_Snappy_ReadPastEndOfBuffer();
snappy::Test_Snappy_FindMatchLength();
snappy::Test_Snappy_FindMatchLengthRandom();
Expand Down
4 changes: 3 additions & 1 deletion snappy.cc
Expand Up @@ -545,7 +545,9 @@ class SnappyDecompressor {
if (n == 0) return false;
const unsigned char c = *(reinterpret_cast<const unsigned char*>(ip));
reader_->Skip(1);
*result |= static_cast<uint32>(c & 0x7f) << shift;
uint32 val = c & 0x7f;
if (((val << shift) >> shift) != val) return false;
*result |= val << shift;
if (c < 128) {
break;
}
Expand Down
14 changes: 14 additions & 0 deletions snappy_unittest.cc
Expand Up @@ -1007,6 +1007,20 @@ TEST(SnappyCorruption, UnterminatedVarint) {
&uncompressed));
}

TEST(SnappyCorruption, OverflowingVarint) {
string compressed, uncompressed;
size_t ulength;
compressed.push_back('\xfb');
compressed.push_back('\xff');
compressed.push_back('\xff');
compressed.push_back('\xff');
compressed.push_back('\x7f');
CHECK(!CheckUncompressedLength(compressed, &ulength));
CHECK(!snappy::IsValidCompressedBuffer(compressed.data(), compressed.size()));
CHECK(!snappy::Uncompress(compressed.data(), compressed.size(),
&uncompressed));
}

TEST(Snappy, ReadPastEndOfBuffer) {
// Check that we do not read past end of input

Expand Down

0 comments on commit 7525a16

Please sign in to comment.