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
This commit is contained in:
Shawn O. Pearce 2012-03-28 10:12:20 -04:00
parent 55bf06b43d
commit 6c0d300a54
7 changed files with 22 additions and 22 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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)

View File

@ -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;
}