aboutsummaryrefslogtreecommitdiff
path: root/src/org/tukaani
diff options
context:
space:
mode:
authorLasse Collin <lasse.collin@tukaani.org>2013-05-11 22:40:30 +0300
committerLasse Collin <lasse.collin@tukaani.org>2013-05-11 22:40:30 +0300
commitd2dc2f3acfbff0c5610b37114d6e278b61e11eb8 (patch)
tree41af4ed5f3346ee203211b4a74407ef0c61af4a7 /src/org/tukaani
parenta896f1956ad1049a7c6efd491e4def09f4d625f1 (diff)
downloadxz-java-d2dc2f3acfbff0c5610b37114d6e278b61e11eb8.tar.gz
Fix data corruption in LZMA2 encoder with flushing or preset dictionary.
Process pending match finder data when flushing or finishing is requested. Previously it was done only when new data was added and only if enough data was added to make it possible for the encoder to encode at least one byte. But if flushing or finishing was requested after adding a few (but not enough) bytes, the pending data wasn't processed and the match finder got out of sync (and could make an assertion fail if assertions were enabled). Bug report: http://sourceforge.net/projects/lzmautils/forums/forum/708858/topic/7796400
Diffstat (limited to 'src/org/tukaani')
-rw-r--r--src/org/tukaani/xz/lz/LZEncoder.java32
1 files changed, 22 insertions, 10 deletions
diff --git a/src/org/tukaani/xz/lz/LZEncoder.java b/src/org/tukaani/xz/lz/LZEncoder.java
index 7cef66a..267d7dd 100644
--- a/src/org/tukaani/xz/lz/LZEncoder.java
+++ b/src/org/tukaani/xz/lz/LZEncoder.java
@@ -205,12 +205,26 @@ public abstract class LZEncoder {
if (writePos >= keepSizeAfter)
readLimit = writePos - keepSizeAfter;
- // After flushing or setting a preset dictionary there may be pending
- // data that hasn't been ran through the match finder yet.
- //
- // NOTE: The test for readLimit is only to avoid wasting time
- // if we get very little new input and thus readLimit wasn't
- // increased above.
+ processPendingBytes();
+
+ // Tell the caller how much input we actually copied into
+ // the dictionary.
+ return len;
+ }
+
+ /**
+ * Process pending bytes remaining from preset dictionary initialization
+ * or encoder flush operation.
+ */
+ private void processPendingBytes() {
+ // After flushing or setting a preset dictionary there will be
+ // pending data that hasn't been ran through the match finder yet.
+ // Run it through the match finder now if there is enough new data
+ // available (readPos < readLimit) that the encoder may encode at
+ // least one more input byte. This way we don't waste any time
+ // looping in the match finder (and marking the same bytes as
+ // pending again) if the application provides very little new data
+ // per write call.
if (pendingSize > 0 && readPos < readLimit) {
readPos -= pendingSize;
int oldPendingSize = pendingSize;
@@ -218,10 +232,6 @@ public abstract class LZEncoder {
skip(oldPendingSize);
assert pendingSize < oldPendingSize;
}
-
- // Tell the caller how much input we actually copied into
- // the dictionary.
- return len;
}
/**
@@ -238,6 +248,7 @@ public abstract class LZEncoder {
*/
public void setFlushing() {
readLimit = writePos - 1;
+ processPendingBytes();
}
/**
@@ -247,6 +258,7 @@ public abstract class LZEncoder {
public void setFinishing() {
readLimit = writePos - 1;
finishing = true;
+ processPendingBytes();
}
/**