diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlock.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlock.java index 7289b9ee9..c1853327f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlock.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlock.java @@ -74,11 +74,6 @@ final class DfsBlock { return block.length; } - int remaining(long pos) { - int ptr = (int) (pos - start); - return block.length - ptr; - } - boolean contains(DfsPackKey want, long pos) { return pack == want && start <= pos && pos < end; } @@ -94,9 +89,11 @@ final class DfsBlock { return n; } - void setInput(Inflater inf, long pos) { + int setInput(long pos, Inflater inf) { int ptr = (int) (pos - start); - inf.setInput(block, ptr, block.length - ptr); + int cnt = block.length - ptr; + inf.setInput(block, ptr, cnt); + return cnt; } void crc32(CRC32 out, long pos, int cnt) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsInserter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsInserter.java index 22a03dd8e..5cab473c3 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsInserter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsInserter.java @@ -460,31 +460,29 @@ public class DfsInserter extends ObjectInserter { } Inflater inf = ctx.inflater(); - DfsBlock b = setInput(inf, pos); + pos += setInput(pos, inf); for (int dstoff = 0;;) { int n = inf.inflate(dstbuf, dstoff, dstbuf.length - dstoff); - if (n > 0) - dstoff += n; - else if (inf.needsInput() && b != null) { - pos += b.remaining(pos); - b = setInput(inf, pos); - } else if (inf.needsInput()) - throw new EOFException(DfsText.get().unexpectedEofInPack); - else if (inf.finished()) + dstoff += n; + if (inf.finished()) return dstbuf; - else + if (inf.needsInput()) + pos += setInput(pos, inf); + else if (n == 0) throw new DataFormatException(); } } - private DfsBlock setInput(Inflater inf, long pos) throws IOException { - if (pos < currPos) { - DfsBlock b = getOrLoadBlock(pos); - b.setInput(inf, pos); - return b; + private int setInput(long pos, Inflater inf) throws IOException { + if (pos < currPos) + return getOrLoadBlock(pos).setInput(pos, inf); + if (pos < currPos + currPtr) { + int s = (int) (pos - currPos); + int n = currPtr - s; + inf.setInput(currBuf, s, n); + return n; } - inf.setInput(currBuf, (int) (pos - currPos), currPtr); - return null; + throw new EOFException(DfsText.get().unexpectedEofInPack); } private DfsBlock getOrLoadBlock(long pos) throws IOException { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReader.java index d7b222866..37dbc7ea7 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReader.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReader.java @@ -600,11 +600,11 @@ public final class DfsReader extends ObjectReader implements ObjectReuseAsIs { * position within the file to read from. * @param dstbuf * destination buffer the inflater should output decompressed - * data to. + * data to. Must be large enough to store the entire stream, + * unless headerOnly is true. * @param headerOnly * if true the caller wants only {@code dstbuf.length} bytes. - * @return updated dstoff based on the number of bytes - * successfully inflated into dstbuf. + * @return number of bytes inflated into dstbuf. * @throws IOException * this cursor does not match the provider or id and the proper * window could not be acquired through the provider's cache. @@ -616,24 +616,17 @@ public final class DfsReader extends ObjectReader implements ObjectReuseAsIs { boolean headerOnly) throws IOException, DataFormatException { prepareInflater(); pin(pack, position); - block.setInput(inf, position); - int dstoff = 0; - for (;;) { + position += block.setInput(position, inf); + for (int dstoff = 0;;) { int n = inf.inflate(dstbuf, dstoff, dstbuf.length - dstoff); - if (n == 0) { - if (headerOnly && dstoff == dstbuf.length) - return dstoff; - if (inf.needsInput()) { - position += block.remaining(position); - pin(pack, position); - block.setInput(inf, position); - continue; - } - if (inf.finished()) - return dstoff; - throw new DataFormatException(); - } dstoff += n; + if (inf.finished() || (headerOnly && dstoff == dstbuf.length)) + return dstoff; + if (inf.needsInput()) { + pin(pack, position); + position += block.setInput(position, inf); + } else if (n == 0) + throw new DataFormatException(); } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java index 81f8ab675..306a0d389 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java @@ -335,7 +335,7 @@ public class PackFile implements Iterable { return null; } - if (curs.inflate(this, position, dstbuf, 0) != sz) + if (curs.inflate(this, position, dstbuf, false) != sz) throw new EOFException(MessageFormat.format( JGitText.get().shortCompressedStreamAt, Long.valueOf(position))); @@ -886,7 +886,7 @@ public class PackFile implements Iterable { // the longest delta instruction header. // final byte[] hdr = new byte[18]; - wc.inflate(this, pos, hdr, 0); + wc.inflate(this, pos, hdr, true /* headerOnly */); return hdr; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCursor.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCursor.java index 8dcbeb896..a0a4c952f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCursor.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCursor.java @@ -290,11 +290,11 @@ final class WindowCursor extends ObjectReader implements ObjectReuseAsIs { * position within the file to read from. * @param dstbuf * destination buffer the inflater should output decompressed - * data to. - * @param dstoff - * current offset within dstbuf to inflate into. - * @return updated dstoff based on the number of bytes - * successfully inflated into dstbuf. + * data to. Must be large enough to store the entire stream, + * unless headerOnly is true. + * @param headerOnly + * if true the caller wants only {@code dstbuf.length} bytes. + * @return number of bytes inflated into dstbuf. * @throws IOException * this cursor does not match the provider or id and the proper * window could not be acquired through the provider's cache. @@ -303,24 +303,21 @@ final class WindowCursor extends ObjectReader implements ObjectReuseAsIs { * stream corruption is likely. */ int inflate(final PackFile pack, long position, final byte[] dstbuf, - int dstoff) throws IOException, DataFormatException { + boolean headerOnly) throws IOException, DataFormatException { prepareInflater(); pin(pack, position); position += window.setInput(position, inf); - do { + for (int dstoff = 0;;) { int n = inf.inflate(dstbuf, dstoff, dstbuf.length - dstoff); - if (n == 0) { - if (inf.needsInput()) { - pin(pack, position); - position += window.setInput(position, inf); - } else if (inf.finished()) - return dstoff; - else - throw new DataFormatException(); - } dstoff += n; - } while (dstoff < dstbuf.length); - return dstoff; + if (inf.finished() || (headerOnly && dstoff == dstbuf.length)) + return dstoff; + if (inf.needsInput()) { + pin(pack, position); + position += window.setInput(position, inf); + } else if (n == 0) + throw new DataFormatException(); + } } ByteArrayWindow quickCopy(PackFile p, long pos, long cnt) 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 c3fdacc27..633554a96 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;