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 66d3d3386b..57d357e4cf 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 @@ public final class PackChunk { 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 @@ public final class PackChunk { 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 @@ public final class PackChunk { 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 f13b543f5e..419e1e8729 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 @@ public final class DfsPackFile { 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 @@ public final class DfsPackFile { 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 @@ public final class DfsPackFile { 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 9965c0e526..95ca4a41f0 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 @@ public class PackFile implements Iterable { 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 @@ public class PackFile implements Iterable { 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 @@ public class PackFile implements Iterable { 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 e3be206825..d059869451 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 @@ public class UnpackedObject { 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 @@ public class UnpackedObject { 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 4c87e87f1b..9e1cbd0e16 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 class BinaryDelta { 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 class BinaryDelta { 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 class BinaryDelta { 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 class BinaryDelta { 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 class BinaryDelta { 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 class BinaryDelta { 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 3c3df90b73..7275729f63 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 abstract class DeltaStream extends InputStream { 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 abstract class DeltaStream extends InputStream { 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 @@ public abstract class DeltaStream extends InputStream { 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 84de99d588..584d9337e1 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 @@ public abstract class PackParser { 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 @@ public abstract class PackParser { while ((c & 0x80) != 0) { c = readFrom(Source.INPUT); hdrBuf[hdrPtr++] = (byte) c; - sz += (c & 0x7f) << shift; + sz += ((long) (c & 0x7f)) << shift; shift += 7; } -- 2.39.5