From e81c49f24c5c316c07d56ca8a9d4ba821ed87ca8 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 11 Feb 2009 18:36:57 -0800 Subject: [PATCH] Validate the pack's footer checksum matches that in the index If the SHA-1 checksum of the entire pack content does not match the checksum stored in the corresponding *.idx file we cannot use the index, as the offsets recorded with it are most likely incorrect. This situation can arise if another application repacks the pack with different compression settings, but puts the same set of objects into it. The offsets are going to be different, but the resulting pack file and index file names will be the same. If we had previously read the old index into memory, but the pack isn't a match anymore, we can't safely access this pack. Signed-off-by: Shawn O. Pearce Signed-off-by: Robin Rosenberg --- org.spearce.jgit/src/org/spearce/jgit/lib/PackFile.java | 11 ++++++++++- org.spearce.jgit/src/org/spearce/jgit/lib/PackIndex.java | 3 +++ org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexV1.java | 3 +++ org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexV2.java | 3 +++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/PackFile.java b/org.spearce.jgit/src/org/spearce/jgit/lib/PackFile.java index d34df039..1e6f170d 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/lib/PackFile.java +++ b/org.spearce.jgit/src/org/spearce/jgit/lib/PackFile.java @@ -42,6 +42,7 @@ import java.io.EOFException; import java.io.File; import java.io.IOException; import java.io.OutputStream; +import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; @@ -265,6 +266,7 @@ public class PackFile implements Iterable { } private void onOpenPack() throws IOException { + final PackIndex idx = idx(); final WindowCursor curs = new WindowCursor(); long position = 0; final byte[] sig = new byte[Constants.PACK_SIGNATURE.length]; @@ -287,11 +289,18 @@ public class PackFile implements Iterable { pack.readFully(position, intbuf, curs); final long packCnt = NB.decodeUInt32(intbuf, 0); - final long idxCnt = idx().getObjectCount(); + final long idxCnt = idx.getObjectCount(); if (idxCnt != packCnt) throw new IOException("Pack index" + " object count mismatch; expected " + packCnt + " found " + idxCnt + ": " + pack.getName()); + + final byte[] csumbuf = new byte[20]; + pack.readFully(pack.length() - 20, csumbuf, curs); + if (!Arrays.equals(csumbuf, idx.packChecksum)) + throw new IOException("Pack index mismatch; pack SHA-1 is " + + ObjectId.fromRaw(csumbuf).name() + ", index expects " + + ObjectId.fromRaw(idx.packChecksum).name()); } private PackedObjectLoader reader(final WindowCursor curs, diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndex.java b/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndex.java index 13acbd1f..473ce1ec 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndex.java +++ b/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndex.java @@ -112,6 +112,9 @@ public abstract class PackIndex implements Iterable { return true; } + /** Footer checksum applied on the bottom of the pack file. */ + protected byte[] packChecksum; + /** * Determine if an object is contained within the pack file. * diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexV1.java b/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexV1.java index 90b5f6f7..fdaa0943 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexV1.java +++ b/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexV1.java @@ -79,6 +79,9 @@ class PackIndexV1 extends PackIndex { } } objectCnt = idxHeader[255]; + + packChecksum = new byte[20]; + NB.readFully(fd, packChecksum, 0, packChecksum.length); } long getObjectCount() { diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexV2.java b/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexV2.java index 48a52065..eb56ed94 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexV2.java +++ b/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexV2.java @@ -142,6 +142,9 @@ class PackIndexV2 extends PackIndex { } else { offset64 = NO_BYTES; } + + packChecksum = new byte[20]; + NB.readFully(fd, packChecksum, 0, packChecksum.length); } @Override -- 2.11.4.GIT