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: I04008728ed828f18202652c3d5401cf95a441d0atags/v2.0.0.201206130900-r
int p = 1; | int p = 1; | ||||
while ((c & 0x80) != 0) { | while ((c & 0x80) != 0) { | ||||
c = dataBuf[posPtr + p++] & 0xff; | c = dataBuf[posPtr + p++] & 0xff; | ||||
sz += (c & 0x7f) << shift; | |||||
sz += ((long) (c & 0x7f)) << shift; | |||||
shift += 7; | shift += 7; | ||||
} | } | ||||
int shift = 4; | int shift = 4; | ||||
while ((c & 0x80) != 0) { | while ((c & 0x80) != 0) { | ||||
c = dataBuf[ptr++] & 0xff; | c = dataBuf[ptr++] & 0xff; | ||||
sz += (c & 0x7f) << shift; | |||||
sz += ((long) (c & 0x7f)) << shift; | |||||
shift += 7; | shift += 7; | ||||
} | } | ||||
int shift = 4; | int shift = 4; | ||||
while ((c & 0x80) != 0) { | while ((c & 0x80) != 0) { | ||||
c = dataBuf[ptr++] & 0xff; | c = dataBuf[ptr++] & 0xff; | ||||
inflatedSize += (c & 0x7f) << shift; | |||||
inflatedSize += ((long) (c & 0x7f)) << shift; | |||||
shift += 7; | shift += 7; | ||||
} | } | ||||
int headerCnt = 1; | int headerCnt = 1; | ||||
while ((c & 0x80) != 0) { | while ((c & 0x80) != 0) { | ||||
c = buf[headerCnt++] & 0xff; | c = buf[headerCnt++] & 0xff; | ||||
inflatedLength += (c & 0x7f) << shift; | |||||
inflatedLength += ((long) (c & 0x7f)) << shift; | |||||
shift += 7; | shift += 7; | ||||
} | } | ||||
int p = 1; | int p = 1; | ||||
while ((c & 0x80) != 0) { | while ((c & 0x80) != 0) { | ||||
c = ib[p++] & 0xff; | c = ib[p++] & 0xff; | ||||
sz += (c & 0x7f) << shift; | |||||
sz += ((long) (c & 0x7f)) << shift; | |||||
shift += 7; | shift += 7; | ||||
} | } | ||||
int p = 1; | int p = 1; | ||||
while ((c & 0x80) != 0) { | while ((c & 0x80) != 0) { | ||||
c = ib[p++] & 0xff; | c = ib[p++] & 0xff; | ||||
sz += (c & 0x7f) << shift; | |||||
sz += ((long) (c & 0x7f)) << shift; | |||||
shift += 7; | shift += 7; | ||||
} | } | ||||
int headerCnt = 1; | int headerCnt = 1; | ||||
while ((c & 0x80) != 0) { | while ((c & 0x80) != 0) { | ||||
c = buf[headerCnt++] & 0xff; | c = buf[headerCnt++] & 0xff; | ||||
inflatedLength += (c & 0x7f) << shift; | |||||
inflatedLength += ((long) (c & 0x7f)) << shift; | |||||
shift += 7; | shift += 7; | ||||
} | } | ||||
int p = 1; | int p = 1; | ||||
while ((c & 0x80) != 0) { | while ((c & 0x80) != 0) { | ||||
c = ib[p++] & 0xff; | c = ib[p++] & 0xff; | ||||
sz += (c & 0x7f) << shift; | |||||
sz += ((long) (c & 0x7f)) << shift; | |||||
shift += 7; | shift += 7; | ||||
} | } | ||||
int p = 1; | int p = 1; | ||||
while ((c & 0x80) != 0) { | while ((c & 0x80) != 0) { | ||||
c = ib[p++] & 0xff; | c = ib[p++] & 0xff; | ||||
sz += (c & 0x7f) << shift; | |||||
sz += ((long) (c & 0x7f)) << shift; | |||||
shift += 7; | shift += 7; | ||||
} | } | ||||
int p = 1; | int p = 1; | ||||
while ((c & 0x80) != 0) { | while ((c & 0x80) != 0) { | ||||
c = hdr[p++] & 0xff; | c = hdr[p++] & 0xff; | ||||
size += (c & 0x7f) << shift; | |||||
size += ((long) (c & 0x7f)) << shift; | |||||
shift += 7; | shift += 7; | ||||
} | } | ||||
int p = 1; | int p = 1; | ||||
while ((c & 0x80) != 0) { | while ((c & 0x80) != 0) { | ||||
c = hdr[p++] & 0xff; | c = hdr[p++] & 0xff; | ||||
size += (c & 0x7f) << shift; | |||||
size += ((long) (c & 0x7f)) << shift; | |||||
shift += 7; | shift += 7; | ||||
} | } | ||||
return size; | return size; |
int c, shift = 0; | int c, shift = 0; | ||||
do { | do { | ||||
c = delta[p++] & 0xff; | c = delta[p++] & 0xff; | ||||
baseLen |= (c & 0x7f) << shift; | |||||
baseLen |= ((long) (c & 0x7f)) << shift; | |||||
shift += 7; | shift += 7; | ||||
} while ((c & 0x80) != 0); | } while ((c & 0x80) != 0); | ||||
return baseLen; | return baseLen; | ||||
int shift = 0; | int shift = 0; | ||||
do { | do { | ||||
c = delta[p++] & 0xff; | c = delta[p++] & 0xff; | ||||
resLen |= (c & 0x7f) << shift; | |||||
resLen |= ((long) (c & 0x7f)) << shift; | |||||
shift += 7; | shift += 7; | ||||
} while ((c & 0x80) != 0); | } while ((c & 0x80) != 0); | ||||
return resLen; | return resLen; | ||||
int c, shift = 0; | int c, shift = 0; | ||||
do { | do { | ||||
c = delta[deltaPtr++] & 0xff; | c = delta[deltaPtr++] & 0xff; | ||||
baseLen |= (c & 0x7f) << shift; | |||||
baseLen |= ((long) (c & 0x7f)) << shift; | |||||
shift += 7; | shift += 7; | ||||
} while ((c & 0x80) != 0); | } while ((c & 0x80) != 0); | ||||
if (base.length != baseLen) | if (base.length != baseLen) | ||||
shift = 0; | shift = 0; | ||||
do { | do { | ||||
c = delta[deltaPtr++] & 0xff; | c = delta[deltaPtr++] & 0xff; | ||||
resLen |= (c & 0x7f) << shift; | |||||
resLen |= ((long) (c & 0x7f)) << shift; | |||||
shift += 7; | shift += 7; | ||||
} while ((c & 0x80) != 0); | } while ((c & 0x80) != 0); | ||||
int c, shift = 0; | int c, shift = 0; | ||||
do { | do { | ||||
c = delta[deltaPtr++] & 0xff; | c = delta[deltaPtr++] & 0xff; | ||||
baseLen |= (c & 0x7f) << shift; | |||||
baseLen |= ((long) (c & 0x7f)) << shift; | |||||
shift += 7; | shift += 7; | ||||
} while ((c & 0x80) != 0); | } while ((c & 0x80) != 0); | ||||
shift = 0; | shift = 0; | ||||
do { | do { | ||||
c = delta[deltaPtr++] & 0xff; | c = delta[deltaPtr++] & 0xff; | ||||
resLen |= (c & 0x7f) << shift; | |||||
resLen |= ((long) (c & 0x7f)) << shift; | |||||
shift += 7; | shift += 7; | ||||
} while ((c & 0x80) != 0); | } while ((c & 0x80) != 0); | ||||
int c, shift = 0; | int c, shift = 0; | ||||
do { | do { | ||||
c = cmdbuf[cmdptr++] & 0xff; | c = cmdbuf[cmdptr++] & 0xff; | ||||
baseSize |= (c & 0x7f) << shift; | |||||
baseSize |= ((long) (c & 0x7f)) << shift; | |||||
shift += 7; | shift += 7; | ||||
} while ((c & 0x80) != 0); | } while ((c & 0x80) != 0); | ||||
shift = 0; | shift = 0; | ||||
do { | do { | ||||
c = cmdbuf[cmdptr++] & 0xff; | c = cmdbuf[cmdptr++] & 0xff; | ||||
resultSize |= (c & 0x7f) << shift; | |||||
resultSize |= ((long) (c & 0x7f)) << shift; | |||||
shift += 7; | shift += 7; | ||||
} while ((c & 0x80) != 0); | } while ((c & 0x80) != 0); | ||||
if ((cmd & 0x04) != 0) | if ((cmd & 0x04) != 0) | ||||
copyOffset |= (cmdbuf[cmdptr++] & 0xff) << 16; | copyOffset |= (cmdbuf[cmdptr++] & 0xff) << 16; | ||||
if ((cmd & 0x08) != 0) | if ((cmd & 0x08) != 0) | ||||
copyOffset |= (cmdbuf[cmdptr++] & 0xff) << 24; | |||||
copyOffset |= ((long) (cmdbuf[cmdptr++] & 0xff)) << 24; | |||||
copySize = 0; | copySize = 0; | ||||
if ((cmd & 0x10) != 0) | if ((cmd & 0x10) != 0) |
while ((c & 0x80) != 0) { | while ((c & 0x80) != 0) { | ||||
c = readFrom(Source.DATABASE); | c = readFrom(Source.DATABASE); | ||||
hdrBuf[hdrPtr++] = (byte) c; | hdrBuf[hdrPtr++] = (byte) c; | ||||
sz += (c & 0x7f) << shift; | |||||
sz += ((long) (c & 0x7f)) << shift; | |||||
shift += 7; | shift += 7; | ||||
} | } | ||||
info.size = sz; | info.size = sz; | ||||
while ((c & 0x80) != 0) { | while ((c & 0x80) != 0) { | ||||
c = readFrom(Source.INPUT); | c = readFrom(Source.INPUT); | ||||
hdrBuf[hdrPtr++] = (byte) c; | hdrBuf[hdrPtr++] = (byte) c; | ||||
sz += (c & 0x7f) << shift; | |||||
sz += ((long) (c & 0x7f)) << shift; | |||||
shift += 7; | shift += 7; | ||||
} | } | ||||