aboutsummaryrefslogtreecommitdiff
path: root/src/org/tukaani
diff options
context:
space:
mode:
authorLasse Collin <lasse.collin@tukaani.org>2014-08-14 21:48:48 +0300
committerLasse Collin <lasse.collin@tukaani.org>2014-08-14 21:48:48 +0300
commit771cc594554d21f5279130b662105fd5dc8bfa88 (patch)
tree712a0992235398b210a3bedbe0dd03e1d1ba6991 /src/org/tukaani
parent84b9c644b91695867635d845dfd610c230d5d875 (diff)
downloadxz-java-771cc594554d21f5279130b662105fd5dc8bfa88.tar.gz
Make it possible to disable verification of integrity checks.
This feature should almost never be used but there are situations where it is useful.
Diffstat (limited to 'src/org/tukaani')
-rw-r--r--src/org/tukaani/xz/BlockInputStream.java14
-rw-r--r--src/org/tukaani/xz/SeekableXZInputStream.java70
-rw-r--r--src/org/tukaani/xz/SingleXZInputStream.java65
-rw-r--r--src/org/tukaani/xz/XZInputStream.java62
4 files changed, 201 insertions, 10 deletions
diff --git a/src/org/tukaani/xz/BlockInputStream.java b/src/org/tukaani/xz/BlockInputStream.java
index 12a8b81..d1e72af 100644
--- a/src/org/tukaani/xz/BlockInputStream.java
+++ b/src/org/tukaani/xz/BlockInputStream.java
@@ -22,6 +22,7 @@ class BlockInputStream extends InputStream {
private final CountingInputStream inCounted;
private InputStream filterChain;
private final Check check;
+ private final boolean verifyCheck;
private long uncompressedSizeInHeader = -1;
private long compressedSizeInHeader = -1;
@@ -32,11 +33,14 @@ class BlockInputStream extends InputStream {
private final byte[] tempBuf = new byte[1];
- public BlockInputStream(InputStream in, Check check, int memoryLimit,
+ public BlockInputStream(InputStream in,
+ Check check, boolean verifyCheck,
+ int memoryLimit,
long unpaddedSizeInIndex,
long uncompressedSizeInIndex)
throws IOException, IndexIndicatorException {
this.check = check;
+ this.verifyCheck = verifyCheck;
inData = new DataInputStream(in);
byte[] buf = new byte[DecoderUtil.BLOCK_HEADER_SIZE_MAX];
@@ -206,7 +210,9 @@ class BlockInputStream extends InputStream {
int ret = filterChain.read(buf, off, len);
if (ret > 0) {
- check.update(buf, off, ret);
+ if (verifyCheck)
+ check.update(buf, off, ret);
+
uncompressedSize += ret;
// Catch invalid values.
@@ -256,10 +262,10 @@ class BlockInputStream extends InputStream {
if (inData.readUnsignedByte() != 0x00)
throw new CorruptedInputException();
- // Validate the integrity check.
+ // Validate the integrity check if verifyCheck is true.
byte[] storedCheck = new byte[check.getSize()];
inData.readFully(storedCheck);
- if (!Arrays.equals(check.finish(), storedCheck))
+ if (verifyCheck && !Arrays.equals(check.finish(), storedCheck))
throw new CorruptedInputException("Integrity check ("
+ check.getName() + ") does not match");
}
diff --git a/src/org/tukaani/xz/SeekableXZInputStream.java b/src/org/tukaani/xz/SeekableXZInputStream.java
index eb5573e..f929d40 100644
--- a/src/org/tukaani/xz/SeekableXZInputStream.java
+++ b/src/org/tukaani/xz/SeekableXZInputStream.java
@@ -138,6 +138,11 @@ public class SeekableXZInputStream extends SeekableInputStream {
private Check check;
/**
+ * Flag indicating if the integrity checks will be verified.
+ */
+ private final boolean verifyCheck;
+
+ /**
* Decoder of the current XZ Block, if any.
*/
private BlockInputStream blockDecoder = null;
@@ -239,6 +244,68 @@ public class SeekableXZInputStream extends SeekableInputStream {
*/
public SeekableXZInputStream(SeekableInputStream in, int memoryLimit)
throws IOException {
+ this(in, memoryLimit, true);
+ }
+
+ /**
+ * Creates a new seekable XZ decomporessor with an optional
+ * memory usage limit and ability to disable verification
+ * of integrity checks.
+ * <p>
+ * Note that integrity check verification should almost never be disabled.
+ * Possible reasons to disable integrity check verification:
+ * <ul>
+ * <li>Trying to recover data from a corrupt .xz file.</li>
+ * <li>Speeding up decompression. This matters mostly with SHA-256
+ * or with files that have compressed extremely well. It's recommended
+ * that integrity checking isn't disabled for performance reasons
+ * unless the file integrity is verified externally in some other
+ * way.</li>
+ * </ul>
+ * <p>
+ * <code>verifyCheck</code> only affects the integrity check of
+ * the actual compressed data. The CRC32 fields in the headers
+ * are always verified.
+ *
+ * @param in seekable input stream containing one or more
+ * XZ Streams; the whole input stream is used
+ *
+ * @param memoryLimit memory usage limit in kibibytes (KiB)
+ * or <code>-1</code> to impose no
+ * memory usage limit
+ *
+ * @param verifyCheck if <code>true</code>, the integrity checks
+ * will be verified; this should almost never
+ * be set to <code>false</code>
+ *
+ * @throws XZFormatException
+ * input is not in the XZ format
+ *
+ * @throws CorruptedInputException
+ * XZ data is corrupt or truncated
+ *
+ * @throws UnsupportedOptionsException
+ * XZ headers seem valid but they specify
+ * options not supported by this implementation
+ *
+ * @throws MemoryLimitException
+ * decoded XZ Indexes would need more memory
+ * than allowed by the memory usage limit
+ *
+ * @throws EOFException
+ * less than 6 bytes of input was available
+ * from <code>in</code>, or (unlikely) the size
+ * of the underlying stream got smaller while
+ * this was reading from it
+ *
+ * @throws IOException may be thrown by <code>in</code>
+ *
+ * @since 1.6
+ */
+ public SeekableXZInputStream(SeekableInputStream in, int memoryLimit,
+ boolean verifyCheck)
+ throws IOException {
+ this.verifyCheck = verifyCheck;
this.in = in;
DataInputStream inData = new DataInputStream(in);
@@ -879,7 +946,8 @@ public class SeekableXZInputStream extends SeekableInputStream {
// Set it to null first so that GC can collect it if memory
// runs tight when initializing a new BlockInputStream.
blockDecoder = null;
- blockDecoder = new BlockInputStream(in, check, memoryLimit,
+ blockDecoder = new BlockInputStream(
+ in, check, verifyCheck, memoryLimit,
curBlockInfo.unpaddedSize, curBlockInfo.uncompressedSize);
} catch (MemoryLimitException e) {
// BlockInputStream doesn't know how much memory we had
diff --git a/src/org/tukaani/xz/SingleXZInputStream.java b/src/org/tukaani/xz/SingleXZInputStream.java
index 6ebddfc..f0c5a16 100644
--- a/src/org/tukaani/xz/SingleXZInputStream.java
+++ b/src/org/tukaani/xz/SingleXZInputStream.java
@@ -44,6 +44,7 @@ public class SingleXZInputStream extends InputStream {
private final int memoryLimit;
private final StreamFlags streamHeaderFlags;
private final Check check;
+ private final boolean verifyCheck;
private BlockInputStream blockDecoder = null;
private final IndexHash indexHash = new IndexHash();
private boolean endReached = false;
@@ -124,13 +125,71 @@ public class SingleXZInputStream extends InputStream {
*/
public SingleXZInputStream(InputStream in, int memoryLimit)
throws IOException {
- this(in, memoryLimit, readStreamHeader(in));
+ this(in, memoryLimit, true, readStreamHeader(in));
}
- SingleXZInputStream(InputStream in, int memoryLimit,
+ /**
+ * Creates a new XZ decompressor that decompresses exactly one
+ * XZ Stream from <code>in</code> with an optional memory usage limit
+ * and ability to disable verification of integrity checks.
+ * <p>
+ * This is identical to <code>SingleXZInputStream(InputStream,int)</code>
+ * except that this takes also the <code>verifyCheck</code> argument.
+ * <p>
+ * Note that integrity check verification should almost never be disabled.
+ * Possible reasons to disable integrity check verification:
+ * <ul>
+ * <li>Trying to recover data from a corrupt .xz file.</li>
+ * <li>Speeding up decompression. This matters mostly with SHA-256
+ * or with files that have compressed extremely well. It's recommended
+ * that integrity checking isn't disabled for performance reasons
+ * unless the file integrity is verified externally in some other
+ * way.</li>
+ * </ul>
+ * <p>
+ * <code>verifyCheck</code> only affects the integrity check of
+ * the actual compressed data. The CRC32 fields in the headers
+ * are always verified.
+ *
+ * @param in input stream from which XZ-compressed
+ * data is read
+ *
+ * @param memoryLimit memory usage limit in kibibytes (KiB)
+ * or <code>-1</code> to impose no
+ * memory usage limit
+ *
+ * @param verifyCheck if <code>true</code>, the integrity checks
+ * will be verified; this should almost never
+ * be set to <code>false</code>
+ *
+ * @throws XZFormatException
+ * input is not in the XZ format
+ *
+ * @throws CorruptedInputException
+ * XZ header CRC32 doesn't match
+ *
+ * @throws UnsupportedOptionsException
+ * XZ header is valid but specifies options
+ * not supported by this implementation
+ *
+ * @throws EOFException
+ * less than 12 bytes of input was available
+ * from <code>in</code>
+ *
+ * @throws IOException may be thrown by <code>in</code>
+ *
+ * @since 1.6
+ */
+ public SingleXZInputStream(InputStream in, int memoryLimit,
+ boolean verifyCheck) throws IOException {
+ this(in, memoryLimit, verifyCheck, readStreamHeader(in));
+ }
+
+ SingleXZInputStream(InputStream in, int memoryLimit, boolean verifyCheck,
byte[] streamHeader) throws IOException {
this.in = in;
this.memoryLimit = memoryLimit;
+ this.verifyCheck = verifyCheck;
streamHeaderFlags = DecoderUtil.decodeStreamHeader(streamHeader);
check = Check.getInstance(streamHeaderFlags.checkType);
}
@@ -235,7 +294,7 @@ public class SingleXZInputStream extends InputStream {
if (blockDecoder == null) {
try {
blockDecoder = new BlockInputStream(
- in, check, memoryLimit, -1, -1);
+ in, check, verifyCheck, memoryLimit, -1, -1);
} catch (IndexIndicatorException e) {
indexHash.validate(in);
validateStreamFooter();
diff --git a/src/org/tukaani/xz/XZInputStream.java b/src/org/tukaani/xz/XZInputStream.java
index bfd71f4..0d460ea 100644
--- a/src/org/tukaani/xz/XZInputStream.java
+++ b/src/org/tukaani/xz/XZInputStream.java
@@ -64,6 +64,7 @@ public class XZInputStream extends InputStream {
private final int memoryLimit;
private InputStream in;
private SingleXZInputStream xzIn;
+ private final boolean verifyCheck;
private boolean endReached = false;
private IOException exception = null;
@@ -129,9 +130,66 @@ public class XZInputStream extends InputStream {
* @throws IOException may be thrown by <code>in</code>
*/
public XZInputStream(InputStream in, int memoryLimit) throws IOException {
+ this(in, memoryLimit, true);
+ }
+
+ /**
+ * Creates a new XZ decompressor with an optional memory usage limit
+ * and ability to disable verification of integrity checks.
+ * <p>
+ * This is identical to <code>XZInputStream(InputStream,int)</code> except
+ * that this takes also the <code>verifyCheck</code> argument.
+ * <p>
+ * Note that integrity check verification should almost never be disabled.
+ * Possible reasons to disable integrity check verification:
+ * <ul>
+ * <li>Trying to recover data from a corrupt .xz file.</li>
+ * <li>Speeding up decompression. This matters mostly with SHA-256
+ * or with files that have compressed extremely well. It's recommended
+ * that integrity checking isn't disabled for performance reasons
+ * unless the file integrity is verified externally in some other
+ * way.</li>
+ * </ul>
+ * <p>
+ * <code>verifyCheck</code> only affects the integrity check of
+ * the actual compressed data. The CRC32 fields in the headers
+ * are always verified.
+ *
+ * @param in input stream from which XZ-compressed
+ * data is read
+ *
+ * @param memoryLimit memory usage limit in kibibytes (KiB)
+ * or <code>-1</code> to impose no
+ * memory usage limit
+ *
+ * @param verifyCheck if <code>true</code>, the integrity checks
+ * will be verified; this should almost never
+ * be set to <code>false</code>
+ *
+ * @throws XZFormatException
+ * input is not in the XZ format
+ *
+ * @throws CorruptedInputException
+ * XZ header CRC32 doesn't match
+ *
+ * @throws UnsupportedOptionsException
+ * XZ header is valid but specifies options
+ * not supported by this implementation
+ *
+ * @throws EOFException
+ * less than 12 bytes of input was available
+ * from <code>in</code>
+ *
+ * @throws IOException may be thrown by <code>in</code>
+ *
+ * @since 1.6
+ */
+ public XZInputStream(InputStream in, int memoryLimit, boolean verifyCheck)
+ throws IOException {
this.in = in;
this.memoryLimit = memoryLimit;
- this.xzIn = new SingleXZInputStream(in, memoryLimit);
+ this.verifyCheck = verifyCheck;
+ this.xzIn = new SingleXZInputStream(in, memoryLimit, verifyCheck);
}
/**
@@ -265,7 +323,7 @@ public class XZInputStream extends InputStream {
inData.readFully(buf, 4, DecoderUtil.STREAM_HEADER_SIZE - 4);
try {
- xzIn = new SingleXZInputStream(in, memoryLimit, buf);
+ xzIn = new SingleXZInputStream(in, memoryLimit, verifyCheck, buf);
} catch (XZFormatException e) {
// Since this isn't the first .xz Stream, it is more
// logical to tell that the data is corrupt.