Skip to content
Merged
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
13 changes: 10 additions & 3 deletions src/java/net/jpountz/lz4/LZ4FrameInputStream.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public class LZ4FrameInputStream extends FilterInputStream {
static final String NOT_SUPPORTED = "Stream unsupported";
static final String BLOCK_HASH_MISMATCH = "Block checksum mismatch";
static final String DESCRIPTOR_HASH_MISMATCH = "Stream frame descriptor corrupted";
static final String INVALID_DESCRIPTOR = "Invalid or unsupported frame descriptor";
static final int MAGIC_SKIPPABLE_BASE = 0x184D2A50;

private final LZ4SafeDecompressor decompressor;
Expand Down Expand Up @@ -203,10 +204,16 @@ private void readHeader() throws IOException {
}

final byte flgByte = (byte) (flgRead & 0xFF);
final LZ4FrameOutputStream.FLG flg = LZ4FrameOutputStream.FLG.fromByte(flgByte);
headerBuffer.put(flgByte);
final byte bdByte = (byte) (bdRead & 0xFF);
final LZ4FrameOutputStream.BD bd = LZ4FrameOutputStream.BD.fromByte(bdByte);
final LZ4FrameOutputStream.FLG flg;
final LZ4FrameOutputStream.BD bd;
try {
flg = LZ4FrameOutputStream.FLG.fromByte(flgByte);
bd = LZ4FrameOutputStream.BD.fromByte(bdByte);
} catch (RuntimeException e) {
throw new IOException(INVALID_DESCRIPTOR, e);
}
headerBuffer.put(flgByte);
headerBuffer.put(bdByte);

final StreamingXXHash32 frameStreamHash;
Expand Down
43 changes: 43 additions & 0 deletions src/test/net/jpountz/lz4/LZ4FrameIOStreamTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* limitations under the License.
*/

import net.jpountz.xxhash.XXHashFactory;
import org.junit.After;
import org.junit.Assert;
import org.junit.Assume;
Expand Down Expand Up @@ -866,4 +867,46 @@ public void testAvailable() throws IOException {
lz4File.delete();
}
}

private static byte[] frameHeader(int flg, int bd) {
final byte[] descriptor = new byte[]{(byte) flg, (byte) bd};
final byte hc = (byte) ((XXHashFactory.fastestInstance().hash32().hash(descriptor, 0, descriptor.length, 0) >> 8) & 0xFF);
final ByteBuffer header = ByteBuffer.allocate(7).order(ByteOrder.LITTLE_ENDIAN);
header.putInt(LZ4FrameOutputStream.MAGIC);
header.put(descriptor);
header.put(hc);
return header.array();
}

private static void assertInvalidDescriptor(IOException e) {
Assert.assertEquals(LZ4FrameInputStream.INVALID_DESCRIPTOR, e.getMessage());
}

@Test
public void testInvalidOrUnsupportedFrameDescriptor() throws IOException {
Assume.assumeTrue(testSize == 0); // does not depend on the test size
final int[][] descriptors = {
{0x40, 0x70}, // dependent blocks
{0x61, 0x70}, // dictionary ID
{0x62, 0x70}, // reserved FLG bit
{0x20, 0x70}, // unsupported version
{0x60, 0x30}, // block size indicator 3
{0x60, 0x41}, // reserved BD bit
};
for (final int[] d : descriptors) {
final byte[] header = frameHeader(d[0], d[1]);
try (InputStream is = new LZ4FrameInputStream(new ByteArrayInputStream(header))) {
assertInvalidDescriptor(Assert.assertThrows(IOException.class, is::read));
}
try (InputStream is = new LZ4FrameInputStream(new ByteArrayInputStream(header))) {
assertInvalidDescriptor(Assert.assertThrows(IOException.class, () -> is.skip(1)));
}
try (LZ4FrameInputStream is = new LZ4FrameInputStream(new ByteArrayInputStream(header), true)) {
assertInvalidDescriptor(Assert.assertThrows(IOException.class, is::getExpectedContentSize));
}
try (LZ4FrameInputStream is = new LZ4FrameInputStream(new ByteArrayInputStream(header), true)) {
assertInvalidDescriptor(Assert.assertThrows(IOException.class, is::isExpectedContentSizeDefined));
}
}
}
}
Loading