This is an automated email from the ASF dual-hosted git repository.
garydgregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git
The following commit(s) were added to refs/heads/master by this push:
new a9597c0b8 Sort members
a9597c0b8 is described below
commit a9597c0b8eb56dc384a508c71297824be06f464b
Author: Gary Gregory <[email protected]>
AuthorDate: Mon Aug 10 18:40:15 2026 -0400
Sort members
---
.../commons/compress/archivers/tar/TarUtils.java | 4 +-
.../compress/archivers/zip/ZipFileTest.java | 106 ++++++++++-----------
.../compress/huffman/HuffmanDecoderTest.java | 32 +++----
3 files changed, 71 insertions(+), 71 deletions(-)
diff --git
a/src/main/java/org/apache/commons/compress/archivers/tar/TarUtils.java
b/src/main/java/org/apache/commons/compress/archivers/tar/TarUtils.java
index 78132cc90..7c93ea218 100644
--- a/src/main/java/org/apache/commons/compress/archivers/tar/TarUtils.java
+++ b/src/main/java/org/apache/commons/compress/archivers/tar/TarUtils.java
@@ -51,8 +51,6 @@
*/
public final class TarUtils {
- private static final char SP = ' ';
-
/**
* Encapsulates the algorithms used up to Commons Compress 1.3 as
ZipEncoding.
*/
@@ -82,6 +80,8 @@ public ByteBuffer encode(final String name) {
}
}
+ private static final char SP = ' ';
+
private static final Pattern HEADER_STRINGS_PATTERN = Pattern.compile(",");
private static final BigInteger NEG_1_BIG_INT = BigInteger.valueOf(-1);
diff --git
a/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileTest.java
b/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileTest.java
index 9c19b0503..0ff9d3bd4 100644
--- a/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileTest.java
+++ b/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileTest.java
@@ -112,6 +112,30 @@ private static void assertEntryName(final
ArrayList<ZipArchiveEntry> entries, fi
assertEquals("src/main/java/org/apache/commons/compress/archivers/zip/" +
expectedName + ".java", ze.getName());
}
+ private static byte[] createZip64Archive() throws IOException {
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ try (ZipArchiveOutputStream zos = new ZipArchiveOutputStream(bos)) {
+ zos.setUseZip64(Zip64Mode.Always);
+ zos.putArchiveEntry(new ZipArchiveEntry("a.txt"));
+ zos.write("hello".getBytes(UTF_8));
+ zos.closeArchiveEntry();
+ }
+ return bos.toByteArray();
+ }
+
+ private static int indexOfSignature(final byte[] data, final byte[]
signature) {
+ for (int i = 0; i + signature.length <= data.length; i++) {
+ int j = 0;
+ while (j < signature.length && data[i + j] == signature[j]) {
+ j++;
+ }
+ if (j == signature.length) {
+ return i;
+ }
+ }
+ return fail("signature not found");
+ }
+
private static void nameSource(final String archive, final String entry,
final ZipArchiveEntry.NameSource expected) throws Exception {
try (ZipFile zf = ZipFile.builder().setURI(getURI(archive)).get()) {
final ZipArchiveEntry ze = zf.getEntry(entry);
@@ -120,6 +144,13 @@ private static void nameSource(final String archive, final
String entry, final Z
}
}
+ private static void writeNegativeLongAt(final byte[] data, final int
offset) {
+ for (int i = 0; i < 8; i++) {
+ data[offset + i] = 0;
+ }
+ data[offset + 7] = (byte) 0x80; // little-endian sign byte -> the
8-byte value is negative
+ }
+
private ZipFile zf;
private void assertAllReadMethods(final byte[] expected, final ZipFile
zipFile, final ZipArchiveEntry entry) throws IOException {
@@ -1079,6 +1110,28 @@ void testWinzipBackSlashWorkaround() throws Exception {
assertNotNull(zf.getEntry("\u00e4/\u00fc.txt"));
}
+ /**
+ * The ZIP64 offsets are 8-byte signed values, so a crafted archive can
make them negative. Feeding such a value straight to
+ * {@link java.nio.channels.SeekableByteChannel#position(long)} used to
throw a raw {@link IllegalArgumentException} out of the {@link ZipFile}
constructor,
+ * which only declares {@link IOException}.
+ */
+ @Test
+ void testZip64NegativeOffsetsAreRejected() throws Exception {
+ final byte[] valid = createZip64Archive();
+ // A well-formed ZIP64 archive still opens.
+ try (ZipFile zf = ZipFile.builder().setByteArray(valid).get()) {
+ assertNotNull(zf.getEntry("a.txt"));
+ }
+ // Negative "relative offset of the ZIP64 end of central directory
record" inside the locator.
+ final byte[] badLocator = valid.clone();
+ writeNegativeLongAt(badLocator, indexOfSignature(badLocator,
ZipArchiveOutputStream.ZIP64_EOCD_LOC_SIG) + 8);
+ assertThrows(ArchiveException.class, () ->
ZipFile.builder().setByteArray(badLocator).get());
+ // Negative "offset of start of central directory" inside the ZIP64
end of central directory record.
+ final byte[] badRecord = valid.clone();
+ writeNegativeLongAt(badRecord, indexOfSignature(badRecord,
ZipArchiveOutputStream.ZIP64_EOCD_SIG) + 48);
+ assertThrows(ArchiveException.class, () ->
ZipFile.builder().setByteArray(badRecord).get());
+ }
+
@Test
void testZipWithShortBeginningGarbage() throws IOException {
final Path path = createTempPath("preamble", ".zip");
@@ -1124,57 +1177,4 @@ void testZstdInputStreamErrorCloseWhenGc() throws
Exception {
}
}
}
-
- private static byte[] createZip64Archive() throws IOException {
- final ByteArrayOutputStream bos = new ByteArrayOutputStream();
- try (ZipArchiveOutputStream zos = new ZipArchiveOutputStream(bos)) {
- zos.setUseZip64(Zip64Mode.Always);
- zos.putArchiveEntry(new ZipArchiveEntry("a.txt"));
- zos.write("hello".getBytes(UTF_8));
- zos.closeArchiveEntry();
- }
- return bos.toByteArray();
- }
-
- private static int indexOfSignature(final byte[] data, final byte[]
signature) {
- for (int i = 0; i + signature.length <= data.length; i++) {
- int j = 0;
- while (j < signature.length && data[i + j] == signature[j]) {
- j++;
- }
- if (j == signature.length) {
- return i;
- }
- }
- return fail("signature not found");
- }
-
- /**
- * The ZIP64 offsets are 8-byte signed values, so a crafted archive can
make them negative. Feeding such a value straight to
- * {@link java.nio.channels.SeekableByteChannel#position(long)} used to
throw a raw {@link IllegalArgumentException} out of the {@link ZipFile}
constructor,
- * which only declares {@link IOException}.
- */
- @Test
- void testZip64NegativeOffsetsAreRejected() throws Exception {
- final byte[] valid = createZip64Archive();
- // A well-formed ZIP64 archive still opens.
- try (ZipFile zf = ZipFile.builder().setByteArray(valid).get()) {
- assertNotNull(zf.getEntry("a.txt"));
- }
- // Negative "relative offset of the ZIP64 end of central directory
record" inside the locator.
- final byte[] badLocator = valid.clone();
- writeNegativeLongAt(badLocator, indexOfSignature(badLocator,
ZipArchiveOutputStream.ZIP64_EOCD_LOC_SIG) + 8);
- assertThrows(ArchiveException.class, () ->
ZipFile.builder().setByteArray(badLocator).get());
- // Negative "offset of start of central directory" inside the ZIP64
end of central directory record.
- final byte[] badRecord = valid.clone();
- writeNegativeLongAt(badRecord, indexOfSignature(badRecord,
ZipArchiveOutputStream.ZIP64_EOCD_SIG) + 48);
- assertThrows(ArchiveException.class, () ->
ZipFile.builder().setByteArray(badRecord).get());
- }
-
- private static void writeNegativeLongAt(final byte[] data, final int
offset) {
- for (int i = 0; i < 8; i++) {
- data[offset + i] = 0;
- }
- data[offset + 7] = (byte) 0x80; // little-endian sign byte -> the
8-byte value is negative
- }
}
diff --git
a/src/test/java/org/apache/commons/compress/huffman/HuffmanDecoderTest.java
b/src/test/java/org/apache/commons/compress/huffman/HuffmanDecoderTest.java
index 8d48e7c41..f44215e58 100644
--- a/src/test/java/org/apache/commons/compress/huffman/HuffmanDecoderTest.java
+++ b/src/test/java/org/apache/commons/compress/huffman/HuffmanDecoderTest.java
@@ -113,6 +113,22 @@ private int decodeSymbol(final HuffmanDecoder decoder,
final int... data) throws
}
}
+ @Test
+ void testCodeLengthBelowMinCodeLength() throws Exception {
+ final int[] codeLengths = new int[] {4, 2, 3, 0, 5, 5, 1};
+ final CompressorException e = assertThrows(CompressorException.class,
() -> new HuffmanDecoder(codeLengths, 1, 5),
+ "Expected CompressorException for code length below min code
length");
+ assertEquals("Invalid code length at symbol 3: 0 (expected in [1,
5])", e.getMessage());
+ }
+
+ @Test
+ void testCodeLengthExceedingMaxCodeLength() throws Exception {
+ final int[] codeLengths = new int[] {4, 2, 3, 0, 5, 5, 1};
+ final CompressorException e = assertThrows(CompressorException.class,
() -> new HuffmanDecoder(codeLengths, 0, 4),
+ "Expected CompressorException for code length exceeding max
code length");
+ assertEquals("Invalid code length at symbol 4: 5 (expected in [0,
4])", e.getMessage());
+ }
+
@Test
void testCreateHuffmanDecodingTablesWithLargeAlphaSize() {
// Use a codeLengths array with length equal to MAX_ALPHA_SIZE (258)
to test array bounds.
@@ -186,22 +202,6 @@ void testNoCodeLengths() throws Exception {
assertEquals("Empty code length list", e.getMessage());
}
- @Test
- void testCodeLengthExceedingMaxCodeLength() throws Exception {
- final int[] codeLengths = new int[] {4, 2, 3, 0, 5, 5, 1};
- final CompressorException e = assertThrows(CompressorException.class,
() -> new HuffmanDecoder(codeLengths, 0, 4),
- "Expected CompressorException for code length exceeding max
code length");
- assertEquals("Invalid code length at symbol 4: 5 (expected in [0,
4])", e.getMessage());
- }
-
- @Test
- void testCodeLengthBelowMinCodeLength() throws Exception {
- final int[] codeLengths = new int[] {4, 2, 3, 0, 5, 5, 1};
- final CompressorException e = assertThrows(CompressorException.class,
() -> new HuffmanDecoder(codeLengths, 1, 5),
- "Expected CompressorException for code length below min code
length");
- assertEquals("Invalid code length at symbol 3: 0 (expected in [1,
5])", e.getMessage());
- }
-
@Test
void testNoLeafNodes() throws Exception {
final HuffmanDecoder decoder = new HuffmanDecoder(new int[] { 0, 0, 0,
0, 0 });