mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-08-29 03:06:45 +08:00
Fix NegativeArraySizeException caused by missing unsigned conversion
Update `ZipContent` so that `eocd.totalNumberOfCentralDirectoryEntries` is converted from a short to an unsigned int to prevent a negative number from being used. This commit also updates the code to consistently use `X.toUnsigned...` helper methods rather than using bitwise operators. Fixed gh-38572
This commit is contained in:
parent
86c2f28cb4
commit
8c7e8778a6
@ -53,8 +53,8 @@ class VirtualZipDataBlock extends VirtualDataBlock implements CloseableDataBlock
|
|||||||
long centralRecordPos = centralRecordPositions[i];
|
long centralRecordPos = centralRecordPositions[i];
|
||||||
DataBlock name = new DataPart(
|
DataBlock name = new DataPart(
|
||||||
centralRecordPos + ZipCentralDirectoryFileHeaderRecord.FILE_NAME_OFFSET + nameOffset,
|
centralRecordPos + ZipCentralDirectoryFileHeaderRecord.FILE_NAME_OFFSET + nameOffset,
|
||||||
(centralRecord.fileNameLength() & 0xFFFF) - nameOffset);
|
Short.toUnsignedLong(centralRecord.fileNameLength()) - nameOffset);
|
||||||
long localRecordPos = centralRecord.offsetToLocalHeader() & 0xFFFFFFFF;
|
long localRecordPos = Integer.toUnsignedLong(centralRecord.offsetToLocalHeader());
|
||||||
ZipLocalFileHeaderRecord localRecord = ZipLocalFileHeaderRecord.load(this.data, localRecordPos);
|
ZipLocalFileHeaderRecord localRecord = ZipLocalFileHeaderRecord.load(this.data, localRecordPos);
|
||||||
DataBlock content = new DataPart(localRecordPos + localRecord.size(), centralRecord.compressedSize());
|
DataBlock content = new DataPart(localRecordPos + localRecord.size(), centralRecord.compressedSize());
|
||||||
boolean hasDescriptorRecord = ZipDataDescriptorRecord.isPresentBasedOnFlag(centralRecord);
|
boolean hasDescriptorRecord = ZipDataDescriptorRecord.isPresentBasedOnFlag(centralRecord);
|
||||||
@ -74,8 +74,8 @@ class VirtualZipDataBlock extends VirtualDataBlock implements CloseableDataBlock
|
|||||||
long originalRecordPos, DataBlock name, int offsetToLocalHeader) throws IOException {
|
long originalRecordPos, DataBlock name, int offsetToLocalHeader) throws IOException {
|
||||||
ZipCentralDirectoryFileHeaderRecord record = originalRecord.withFileNameLength((short) (name.size() & 0xFFFF))
|
ZipCentralDirectoryFileHeaderRecord record = originalRecord.withFileNameLength((short) (name.size() & 0xFFFF))
|
||||||
.withOffsetToLocalHeader(offsetToLocalHeader);
|
.withOffsetToLocalHeader(offsetToLocalHeader);
|
||||||
int originalExtraFieldLength = originalRecord.extraFieldLength() & 0xFFFF;
|
int originalExtraFieldLength = Short.toUnsignedInt(originalRecord.extraFieldLength());
|
||||||
int originalFileCommentLength = originalRecord.fileCommentLength() & 0xFFFF;
|
int originalFileCommentLength = Short.toUnsignedInt(originalRecord.fileCommentLength());
|
||||||
DataBlock extraFieldAndComment = new DataPart(
|
DataBlock extraFieldAndComment = new DataPart(
|
||||||
originalRecordPos + originalRecord.size() - originalExtraFieldLength - originalFileCommentLength,
|
originalRecordPos + originalRecord.size() - originalExtraFieldLength - originalFileCommentLength,
|
||||||
originalExtraFieldLength + originalFileCommentLength);
|
originalExtraFieldLength + originalFileCommentLength);
|
||||||
@ -89,8 +89,8 @@ class VirtualZipDataBlock extends VirtualDataBlock implements CloseableDataBlock
|
|||||||
ZipLocalFileHeaderRecord originalRecord, ZipDataDescriptorRecord dataDescriptorRecord, DataBlock name,
|
ZipLocalFileHeaderRecord originalRecord, ZipDataDescriptorRecord dataDescriptorRecord, DataBlock name,
|
||||||
DataBlock content) throws IOException {
|
DataBlock content) throws IOException {
|
||||||
ZipLocalFileHeaderRecord record = originalRecord.withFileNameLength((short) (name.size() & 0xFFFF));
|
ZipLocalFileHeaderRecord record = originalRecord.withFileNameLength((short) (name.size() & 0xFFFF));
|
||||||
long originalRecordPos = centralRecord.offsetToLocalHeader() & 0xFFFFFFFF;
|
long originalRecordPos = Integer.toUnsignedLong(centralRecord.offsetToLocalHeader());
|
||||||
int extraFieldLength = originalRecord.extraFieldLength() & 0xFFFF;
|
int extraFieldLength = Short.toUnsignedInt(originalRecord.extraFieldLength());
|
||||||
parts.add(new ByteArrayDataBlock(record.asByteArray()));
|
parts.add(new ByteArrayDataBlock(record.asByteArray()));
|
||||||
parts.add(name);
|
parts.add(name);
|
||||||
parts.add(new DataPart(originalRecordPos + originalRecord.size() - extraFieldLength, extraFieldLength));
|
parts.add(new DataPart(originalRecordPos + originalRecord.size() - extraFieldLength, extraFieldLength));
|
||||||
|
@ -83,14 +83,14 @@ record ZipCentralDirectoryFileHeaderRecord(short versionMadeBy, short versionNee
|
|||||||
* @throws IOException on I/O error
|
* @throws IOException on I/O error
|
||||||
*/
|
*/
|
||||||
void copyTo(DataBlock dataBlock, long pos, ZipEntry zipEntry) throws IOException {
|
void copyTo(DataBlock dataBlock, long pos, ZipEntry zipEntry) throws IOException {
|
||||||
int fileNameLength = fileNameLength() & 0xFFFF;
|
int fileNameLength = Short.toUnsignedInt(fileNameLength());
|
||||||
int extraLength = extraFieldLength() & 0xFFFF;
|
int extraLength = Short.toUnsignedInt(extraFieldLength());
|
||||||
int commentLength = fileCommentLength() & 0xFFFF;
|
int commentLength = Short.toUnsignedInt(fileCommentLength());
|
||||||
zipEntry.setMethod(compressionMethod() & 0xFFFF);
|
zipEntry.setMethod(Short.toUnsignedInt(compressionMethod()));
|
||||||
zipEntry.setTime(decodeMsDosFormatDateTime(lastModFileDate(), lastModFileTime()));
|
zipEntry.setTime(decodeMsDosFormatDateTime(lastModFileDate(), lastModFileTime()));
|
||||||
zipEntry.setCrc(crc32() & 0xFFFFFFFFL);
|
zipEntry.setCrc(Integer.toUnsignedLong(crc32()));
|
||||||
zipEntry.setCompressedSize(compressedSize() & 0xFFFFFFFFL);
|
zipEntry.setCompressedSize(Integer.toUnsignedLong(compressedSize()));
|
||||||
zipEntry.setSize(uncompressedSize() & 0xFFFFFFFFL);
|
zipEntry.setSize(Integer.toUnsignedLong(uncompressedSize()));
|
||||||
if (extraLength > 0) {
|
if (extraLength > 0) {
|
||||||
long extraPos = pos + MINIMUM_SIZE + fileNameLength;
|
long extraPos = pos + MINIMUM_SIZE + fileNameLength;
|
||||||
ByteBuffer buffer = ByteBuffer.allocate(extraLength);
|
ByteBuffer buffer = ByteBuffer.allocate(extraLength);
|
||||||
|
@ -556,13 +556,16 @@ public final class ZipContent implements Closeable {
|
|||||||
Zip64EndOfCentralDirectoryRecord zip64Eocd = Zip64EndOfCentralDirectoryRecord.load(data, zip64Locator);
|
Zip64EndOfCentralDirectoryRecord zip64Eocd = Zip64EndOfCentralDirectoryRecord.load(data, zip64Locator);
|
||||||
data = data.slice(getStartOfZipContent(data, eocd, zip64Eocd));
|
data = data.slice(getStartOfZipContent(data, eocd, zip64Eocd));
|
||||||
long centralDirectoryPos = (zip64Eocd != null) ? zip64Eocd.offsetToStartOfCentralDirectory()
|
long centralDirectoryPos = (zip64Eocd != null) ? zip64Eocd.offsetToStartOfCentralDirectory()
|
||||||
: eocd.offsetToStartOfCentralDirectory();
|
: Integer.toUnsignedLong(eocd.offsetToStartOfCentralDirectory());
|
||||||
long numberOfEntries = (zip64Eocd != null) ? zip64Eocd.totalNumberOfCentralDirectoryEntries()
|
long numberOfEntries = (zip64Eocd != null) ? zip64Eocd.totalNumberOfCentralDirectoryEntries()
|
||||||
: eocd.totalNumberOfCentralDirectoryEntries();
|
: Short.toUnsignedInt(eocd.totalNumberOfCentralDirectoryEntries());
|
||||||
if (numberOfEntries > 0xFFFFFFFFL) {
|
if (numberOfEntries < 0) {
|
||||||
|
throw new IllegalStateException("Invalid number of zip entries in " + source);
|
||||||
|
}
|
||||||
|
if (numberOfEntries > Integer.MAX_VALUE) {
|
||||||
throw new IllegalStateException("Too many zip entries in " + source);
|
throw new IllegalStateException("Too many zip entries in " + source);
|
||||||
}
|
}
|
||||||
Loader loader = new Loader(source, null, data, centralDirectoryPos, (int) (numberOfEntries & 0xFFFFFFFFL));
|
Loader loader = new Loader(source, null, data, centralDirectoryPos, (int) numberOfEntries);
|
||||||
ByteBuffer signatureNameSuffixBuffer = ByteBuffer.allocate(SIGNATURE_SUFFIX.length);
|
ByteBuffer signatureNameSuffixBuffer = ByteBuffer.allocate(SIGNATURE_SUFFIX.length);
|
||||||
boolean hasJarSignatureFile = false;
|
boolean hasJarSignatureFile = false;
|
||||||
long pos = centralDirectoryPos;
|
long pos = centralDirectoryPos;
|
||||||
|
@ -286,7 +286,7 @@ final class ZipString {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static int getCodePointSize(byte[] bytes, int i) {
|
private static int getCodePointSize(byte[] bytes, int i) {
|
||||||
int b = bytes[i] & 0xFF;
|
int b = Byte.toUnsignedInt(bytes[i]);
|
||||||
if ((b & 0b1_0000000) == 0b0_0000000) {
|
if ((b & 0b1_0000000) == 0b0_0000000) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -300,7 +300,7 @@ final class ZipString {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static int getCodePoint(byte[] bytes, int i, int codePointSize) {
|
private static int getCodePoint(byte[] bytes, int i, int codePointSize) {
|
||||||
int codePoint = bytes[i] & 0xFF;
|
int codePoint = Byte.toUnsignedInt(bytes[i]);
|
||||||
codePoint &= INITIAL_BYTE_BITMASK[codePointSize - 1];
|
codePoint &= INITIAL_BYTE_BITMASK[codePointSize - 1];
|
||||||
for (int j = 1; j < codePointSize; j++) {
|
for (int j = 1; j < codePointSize; j++) {
|
||||||
codePoint = (codePoint << 6) + (bytes[i + j] & SUBSEQUENT_BYTE_BITMASK);
|
codePoint = (codePoint << 6) + (bytes[i + j] & SUBSEQUENT_BYTE_BITMASK);
|
||||||
|
Loading…
Reference in New Issue
Block a user