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
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 66d3d33..57d357e 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 f13b543..419e1e8 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 9965c0e..95ca4a4 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 e3be206..d059869 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 4c87e87..9e1cbd0 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 long getResultSize(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 long getResultSize(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 3c3df90..7275729 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 84de99d..584d933 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;
 		}