From 6c0d300a54f14fcfbd05dab5756097986b20eca8 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 28 Mar 2012 10:12:20 -0400 Subject: [PATCH] Fix loading packed objects >2G Parsing the size from a packed object header was incorrectly computing the total inflated length when the length exceeded the range of a Java int. The next 7 bits of size information was shifted left as an int using a shift of 25 bits, placing the higher bits of the size into the sign position. When this size was extended to a long to be added to the current size accumulator the size went negative, resulting in NegativeArraySizeException being thrown. Fix all places where this particular pattern of code is used to read a pack size field, or a binary delta header, as they both use the same variable length encoding scheme. Change-Id: I04008728ed828f18202652c3d5401cf95a441d0a --- .../src/org/eclipse/jgit/storage/dht/PackChunk.java | 6 +++--- .../org/eclipse/jgit/storage/dfs/DfsPackFile.java | 6 +++--- .../src/org/eclipse/jgit/storage/file/PackFile.java | 6 +++--- .../eclipse/jgit/storage/file/UnpackedObject.java | 4 ++-- .../org/eclipse/jgit/storage/pack/BinaryDelta.java | 12 ++++++------ .../org/eclipse/jgit/storage/pack/DeltaStream.java | 6 +++--- .../src/org/eclipse/jgit/transport/PackParser.java | 4 ++-- 7 files changed, 22 insertions(+), 22 deletions(-) diff --git a/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/PackChunk.java b/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/PackChunk.java index 66d3d3386..57d357e4c 100644 --- a/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/PackChunk.java +++ b/org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/PackChunk.java @@ -349,7 +349,7 @@ private static ObjectLoader read1(PackChunk pc, int pos, int p = 1; while ((c & 0x80) != 0) { c = dataBuf[posPtr + p++] & 0xff; - sz += (c & 0x7f) << shift; + sz += ((long) (c & 0x7f)) << shift; shift += 7; } @@ -603,7 +603,7 @@ int readObjectTypeAndSize(int ptr, PackParser.ObjectTypeAndSize info) { int shift = 4; while ((c & 0x80) != 0) { c = dataBuf[ptr++] & 0xff; - sz += (c & 0x7f) << shift; + sz += ((long) (c & 0x7f)) << shift; shift += 7; } @@ -650,7 +650,7 @@ void copyObjectAsIs(PackOutputStream out, DhtObjectToPack obj, int shift = 4; while ((c & 0x80) != 0) { c = dataBuf[ptr++] & 0xff; - inflatedSize += (c & 0x7f) << shift; + inflatedSize += ((long) (c & 0x7f)) << shift; shift += 7; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/dfs/DfsPackFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/dfs/DfsPackFile.java index f13b543f5..419e1e872 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/dfs/DfsPackFile.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/dfs/DfsPackFile.java @@ -395,7 +395,7 @@ void copyAsIs(PackOutputStream out, DfsObjectToPack src, int headerCnt = 1; while ((c & 0x80) != 0) { c = buf[headerCnt++] & 0xff; - inflatedLength += (c & 0x7f) << shift; + inflatedLength += ((long) (c & 0x7f)) << shift; shift += 7; } @@ -676,7 +676,7 @@ ObjectLoader load(DfsReader ctx, long pos) int p = 1; while ((c & 0x80) != 0) { c = ib[p++] & 0xff; - sz += (c & 0x7f) << shift; + sz += ((long) (c & 0x7f)) << shift; shift += 7; } @@ -907,7 +907,7 @@ long getObjectSize(DfsReader ctx, long pos) int p = 1; while ((c & 0x80) != 0) { c = ib[p++] & 0xff; - sz += (c & 0x7f) << shift; + sz += ((long) (c & 0x7f)) << shift; shift += 7; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/PackFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/PackFile.java index 9965c0e52..95ca4a41f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/PackFile.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/PackFile.java @@ -345,7 +345,7 @@ private void copyAsIs2(PackOutputStream out, LocalObjectToPack src, int headerCnt = 1; while ((c & 0x80) != 0) { c = buf[headerCnt++] & 0xff; - inflatedLength += (c & 0x7f) << shift; + inflatedLength += ((long) (c & 0x7f)) << shift; shift += 7; } @@ -684,7 +684,7 @@ ObjectLoader load(final WindowCursor curs, long pos) int p = 1; while ((c & 0x80) != 0) { c = ib[p++] & 0xff; - sz += (c & 0x7f) << shift; + sz += ((long) (c & 0x7f)) << shift; shift += 7; } @@ -929,7 +929,7 @@ long getObjectSize(final WindowCursor curs, final long pos) int p = 1; while ((c & 0x80) != 0) { c = ib[p++] & 0xff; - sz += (c & 0x7f) << shift; + sz += ((long) (c & 0x7f)) << shift; shift += 7; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/UnpackedObject.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/UnpackedObject.java index e3be20682..d05986945 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/UnpackedObject.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/UnpackedObject.java @@ -151,7 +151,7 @@ static ObjectLoader open(InputStream in, File path, AnyObjectId id, int p = 1; while ((c & 0x80) != 0) { c = hdr[p++] & 0xff; - size += (c & 0x7f) << shift; + size += ((long) (c & 0x7f)) << shift; shift += 7; } @@ -224,7 +224,7 @@ static long getSize(InputStream in, AnyObjectId id, WindowCursor wc) int p = 1; while ((c & 0x80) != 0) { c = hdr[p++] & 0xff; - size += (c & 0x7f) << shift; + size += ((long) (c & 0x7f)) << shift; shift += 7; } return size; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/BinaryDelta.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/BinaryDelta.java index 4c87e87f1..9e1cbd0e1 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/BinaryDelta.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/BinaryDelta.java @@ -70,7 +70,7 @@ public static long getBaseSize(final byte[] delta) { int c, shift = 0; do { c = delta[p++] & 0xff; - baseLen |= (c & 0x7f) << shift; + baseLen |= ((long) (c & 0x7f)) << shift; shift += 7; } while ((c & 0x80) != 0); return baseLen; @@ -97,7 +97,7 @@ public static long getResultSize(final byte[] delta) { int shift = 0; do { c = delta[p++] & 0xff; - resLen |= (c & 0x7f) << shift; + resLen |= ((long) (c & 0x7f)) << shift; shift += 7; } while ((c & 0x80) != 0); return resLen; @@ -142,7 +142,7 @@ public static final byte[] apply(final byte[] base, final byte[] delta, int c, shift = 0; do { c = delta[deltaPtr++] & 0xff; - baseLen |= (c & 0x7f) << shift; + baseLen |= ((long) (c & 0x7f)) << shift; shift += 7; } while ((c & 0x80) != 0); if (base.length != baseLen) @@ -155,7 +155,7 @@ public static final byte[] apply(final byte[] base, final byte[] delta, shift = 0; do { c = delta[deltaPtr++] & 0xff; - resLen |= (c & 0x7f) << shift; + resLen |= ((long) (c & 0x7f)) << shift; shift += 7; } while ((c & 0x80) != 0); @@ -243,7 +243,7 @@ public static String format(byte[] delta, boolean includeHeader) { int c, shift = 0; do { c = delta[deltaPtr++] & 0xff; - baseLen |= (c & 0x7f) << shift; + baseLen |= ((long) (c & 0x7f)) << shift; shift += 7; } while ((c & 0x80) != 0); @@ -251,7 +251,7 @@ public static String format(byte[] delta, boolean includeHeader) { shift = 0; do { c = delta[deltaPtr++] & 0xff; - resLen |= (c & 0x7f) << shift; + resLen |= ((long) (c & 0x7f)) << shift; shift += 7; } while ((c & 0x80) != 0); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/DeltaStream.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/DeltaStream.java index 3c3df90b7..7275729f6 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/DeltaStream.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/DeltaStream.java @@ -114,7 +114,7 @@ public DeltaStream(final InputStream deltaStream) throws IOException { int c, shift = 0; do { c = cmdbuf[cmdptr++] & 0xff; - baseSize |= (c & 0x7f) << shift; + baseSize |= ((long) (c & 0x7f)) << shift; shift += 7; } while ((c & 0x80) != 0); @@ -123,7 +123,7 @@ public DeltaStream(final InputStream deltaStream) throws IOException { shift = 0; do { c = cmdbuf[cmdptr++] & 0xff; - resultSize |= (c & 0x7f) << shift; + resultSize |= ((long) (c & 0x7f)) << shift; shift += 7; } while ((c & 0x80) != 0); @@ -286,7 +286,7 @@ private int next() throws IOException { if ((cmd & 0x04) != 0) copyOffset |= (cmdbuf[cmdptr++] & 0xff) << 16; if ((cmd & 0x08) != 0) - copyOffset |= (cmdbuf[cmdptr++] & 0xff) << 24; + copyOffset |= ((long) (cmdbuf[cmdptr++] & 0xff)) << 24; copySize = 0; if ((cmd & 0x10) != 0) 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 84de99d58..584d9337e 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java @@ -681,7 +681,7 @@ protected ObjectTypeAndSize readObjectHeader(ObjectTypeAndSize info) while ((c & 0x80) != 0) { c = readFrom(Source.DATABASE); hdrBuf[hdrPtr++] = (byte) c; - sz += (c & 0x7f) << shift; + sz += ((long) (c & 0x7f)) << shift; shift += 7; } info.size = sz; @@ -892,7 +892,7 @@ private void indexOneObject() throws IOException { while ((c & 0x80) != 0) { c = readFrom(Source.INPUT); hdrBuf[hdrPtr++] = (byte) c; - sz += (c & 0x7f) << shift; + sz += ((long) (c & 0x7f)) << shift; shift += 7; }