Merge pull request #143 from xerial/fix-header-check

#142: Fix reading stream that happens to have MAGIC_HEADER[0]
This commit is contained in:
Taro L. Saito 2016-06-02 10:35:07 -07:00
commit 1f54055894
3 changed files with 46 additions and 1 deletions

View File

@ -120,6 +120,18 @@ public class SnappyCodec
return Arrays.equals(MAGIC_HEADER, magic); return Arrays.equals(MAGIC_HEADER, magic);
} }
public static boolean hasMagicHeaderPrefix(byte[] b) {
int limit = Math.min(MAGIC_LEN, b.length);
int i = 0;
while(i < limit) {
if(b[i] != MAGIC_HEADER[i]) {
return false;
}
++i;
}
return true;
}
public static SnappyCodec readHeader(InputStream in) public static SnappyCodec readHeader(InputStream in)
throws IOException throws IOException
{ {

View File

@ -93,7 +93,7 @@ public class SnappyInputStream
// Snappy produces at least 1-byte result. So the empty input is not a valid input // Snappy produces at least 1-byte result. So the empty input is not a valid input
throw new SnappyIOException(SnappyErrorCode.EMPTY_INPUT, "Cannot decompress empty stream"); throw new SnappyIOException(SnappyErrorCode.EMPTY_INPUT, "Cannot decompress empty stream");
} }
if (readBytes < header.length || header[0] != SnappyCodec.MAGIC_HEADER[0]) { if (readBytes < header.length || !SnappyCodec.hasMagicHeaderPrefix(header)) {
// do the default uncompression // do the default uncompression
// (probably) compressed by Snappy.compress(byte[]) // (probably) compressed by Snappy.compress(byte[])
readFully(header, readBytes); readFully(header, readBytes);

View File

@ -204,4 +204,37 @@ public class SnappyInputStreamTest
assertArrayEquals(orig, uncompressed); assertArrayEquals(orig, uncompressed);
} }
@Test
public void checkMagicHeader()
throws IOException
{
ByteArrayOutputStream b = new ByteArrayOutputStream();
// Write uncompressed length beginning with -126 (the same with magicheader[0])
b.write(SnappyCodec.MAGIC_HEADER[0]);
b.write(0x01);
// uncompressed data length = 130
ByteArrayOutputStream data = new ByteArrayOutputStream();
for(int i=0; i<130; ++i) {
data.write('A');
}
byte[] dataMoreThan8Len = data.toByteArray();
// write literal (lower 2-bit of the first tag byte is 00, upper 6-bits represents data size)
b.write(60<<2); // 1-byte data length follows
b.write(dataMoreThan8Len.length-1); // subsequent data length
b.write(dataMoreThan8Len);
byte[] compressed = b.toByteArray();
// This should succeed
assertArrayEquals(dataMoreThan8Len, Snappy.uncompress(compressed));
// Reproduce error in #142
SnappyInputStream in = new SnappyInputStream(new ByteArrayInputStream(b.toByteArray()));
byte[] uncompressed = readFully(in);
assertArrayEquals(dataMoreThan8Len, uncompressed);
}
} }