aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java
diff options
context:
space:
mode:
authorShawn Pearce <spearce@spearce.org>2014-08-13 16:54:22 -0700
committerShawn Pearce <sop@google.com>2014-08-14 12:36:43 -0700
commit94c4d7eee85d5ffe19d04c5a6e60192430d4fe1e (patch)
tree9ee3c8dcbb5d35ea0f93ac045c75feb3f843abe8 /org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java
parent861f5f649f9beba153557f443db1d5706782961e (diff)
downloadjgit-94c4d7eee85d5ffe19d04c5a6e60192430d4fe1e.tar.gz
jgit-94c4d7eee85d5ffe19d04c5a6e60192430d4fe1e.zip
Cleanup use of java.util.Inflater, fixing rare infinite loops
The native implementation of inflate() can set finished to return true at the same time as it copies the last bytes into the buffer. Check for finished on each iteration, terminating as soon as libz knows the stream was completely inflated. If not finished, it is likely input is required before the next native call could do any useful work. Most invocations are passing in a buffer large enough to store the entire result. A partial return from inflate() will need more input before it can continue. Checking right away that needsInput() is true saves a native call to determine no bytes can be inflated without more input. This should fix a rare infinite loop condition inside of inflation when an object ends exactly at the end of a block boundary, and the next block contains only the 20 byte trailing SHA-1. When the stream is finished each new attempt to inflate() returns n == 0, as no additional bytes were output. The needsInput() test tries to add the length of the footer block to itself, but then loops back around an reloads the same block as the block is smaller than a full block size. A zero length input is set to the inflater, which triggers needsInput() condition again. Change-Id: I95d02bfeab4bf995a254d49166b4ae62d1f21346
Diffstat (limited to 'org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java31
1 files changed, 13 insertions, 18 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java
index c3fdacc27a..633554a96f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java
@@ -1653,24 +1653,19 @@ public abstract class PackParser {
int n = 0;
while (n < cnt) {
int r = inf.inflate(dst, pos + n, cnt - n);
- if (r == 0) {
- if (inf.finished())
- break;
- if (inf.needsInput()) {
- onObjectData(src, buf, p, bAvail);
- use(bAvail);
-
- p = fill(src, 1);
- inf.setInput(buf, p, bAvail);
- } else {
- throw new CorruptObjectException(
- MessageFormat
- .format(
- JGitText.get().packfileCorruptionDetected,
- JGitText.get().unknownZlibError));
- }
- } else {
- n += r;
+ n += r;
+ if (inf.finished())
+ break;
+ if (inf.needsInput()) {
+ onObjectData(src, buf, p, bAvail);
+ use(bAvail);
+
+ p = fill(src, 1);
+ inf.setInput(buf, p, bAvail);
+ } else if (r == 0) {
+ throw new CorruptObjectException(MessageFormat.format(
+ JGitText.get().packfileCorruptionDetected,
+ JGitText.get().unknownZlibError));
}
}
actualSize += n;