From 06d7d84ad55da0b00f6d3f2e615f991f77a6b5a6 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Mon, 18 Aug 2008 09:35:33 -0700 Subject: [PATCH] Fix DirCache's skip over null byte padding when reading a DIRC file Sometimes we hit EOFException while reading from a 'DIRC' file with the new DirCache API. This was caused by BufferedInputStream.skip skipping only part of the range we asked it to skip if the range we asked it to skip spanned over the end of the current buffer block. Two skip requests are necessary in this case: one to force the stream to skip to the end of the buffer, and another to skip over data in the source stream before reading the next buffer block into memory. NB.skipFully handles this by abstracting the necessary loop into a utility function, much like NB.readFully handles the necessary read loop to ensure we read a full block of data. DirCacheEntry and DirCache both need to use this routine to skip over the parts of the DIRC file they do not wish to read. Signed-off-by: Shawn O. Pearce Signed-off-by: Robin Rosenberg --- .../src/org/spearce/jgit/dircache/DirCache.java | 2 +- .../org/spearce/jgit/dircache/DirCacheEntry.java | 2 +- org.spearce.jgit/src/org/spearce/jgit/util/NB.java | 27 ++++++++++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCache.java b/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCache.java index 995942c3..76657c47 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCache.java +++ b/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCache.java @@ -370,7 +370,7 @@ public class DirCache { // a performance optimization. Since we do not // understand it, we can safely skip past it. // - in.skip(NB.decodeInt32(hdr, 4)); + NB.skipFully(in, NB.decodeUInt32(hdr, 4)); } else { // The extension is not an optimization and is // _required_ to understand this index format. diff --git a/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCacheEntry.java b/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCacheEntry.java index bcf55969..011bc16c 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCacheEntry.java +++ b/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCacheEntry.java @@ -116,7 +116,7 @@ public class DirCacheEntry { final int actLen = INFO_LEN + pathLen; final int expLen = (actLen + 8) & ~7; if (actLen != expLen) - in.skip(expLen - actLen); + NB.skipFully(in, expLen - actLen); } /** diff --git a/org.spearce.jgit/src/org/spearce/jgit/util/NB.java b/org.spearce.jgit/src/org/spearce/jgit/util/NB.java index fa13354c..c65c6fa1 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/util/NB.java +++ b/org.spearce.jgit/src/org/spearce/jgit/util/NB.java @@ -71,6 +71,33 @@ public final class NB { } /** + * Skip an entire region of an input stream. + *

+ * The input stream's position is moved forward by the number of requested + * bytes, discarding them from the input. This method does not return until + * the exact number of bytes requested has been skipped. + * + * @param fd + * the stream to skip bytes from. + * @param toSkip + * total number of bytes to be discarded. Must be >= 0. + * @throws EOFException + * the stream ended before the requested number of bytes were + * skipped. + * @throws IOException + * there was an error reading from the stream. + */ + public static void skipFully(final InputStream fd, long toSkip) + throws IOException { + while (toSkip > 0) { + final long r = fd.skip(toSkip); + if (r <= 0) + throw new EOFException("Short skip of block"); + toSkip -= r; + } + } + + /** * Compare a 32 bit unsigned integer stored in a 32 bit signed integer. *

* This function performs an unsigned compare operation, even though Java -- 2.11.4.GIT