You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2026/08/16 14:47:00 UTC
(commons-compress) branch master updated (2586fab41 -> 1ecd39bc5)
This is an automated email from the ASF dual-hosted git repository.
garydgregory pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git
from 2586fab41 [Unpack200] Reject out-of-range cpUTF8Prefix in CpBands.parseCpUtf8 (#800).
new 9b613b8b1 Move action to its proper section.
new 1ecd39bc5 [GZip] GzipCompressorInputStream now throws CompressorException instead of IllegalArgumetException/IllegalStateException.
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
src/changes/changes.xml | 3 +-
.../compress/compressors/gzip/GzipParameters.java | 17 ++++---
.../gzip/GzipCompressorInputStreamTest.java | 58 ++++++++++++++++++++++
.../compressors/gzip/GzipParametersTest.java | 9 ++--
4 files changed, 73 insertions(+), 14 deletions(-)
(commons-compress) 02/02: [GZip] GzipCompressorInputStream now throws CompressorException instead of IllegalArgumetException/IllegalStateException.
Posted by gg...@apache.org.
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
commit 1ecd39bc5bda8b3b529aabd0a80384bed41a4984
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Sun Aug 16 10:46:52 2026 -0400
[GZip] GzipCompressorInputStream now throws CompressorException instead
of IllegalArgumetException/IllegalStateException.
---
src/changes/changes.xml | 2 +-
.../compress/compressors/gzip/GzipParameters.java | 17 ++++---
.../gzip/GzipCompressorInputStreamTest.java | 58 ++++++++++++++++++++++
.../compressors/gzip/GzipParametersTest.java | 9 ++--
4 files changed, 73 insertions(+), 13 deletions(-)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 3ab6c4fe2..f4e45f82a 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -149,7 +149,7 @@ The <action> type attribute can be add,update,fix,remove.
<!-- FIX gzip -->
<action type="fix" dev="ggregory" due-to="Gary Gregory">[GZip] GzipParameters.setOperatingSystem(int) now throws CompressorException on illegal input.</action>
<action type="fix" issue="COMPRESS-705" dev="ggregory" due-to="Mario Fredenhagen, Gary Gregory">[GZip] GZip IOException: Extra subfield length exceeds remaining bytes in extra field; use new option GzipCompressorInputStream.Builder.setIgnoreExtraField(boolean).</action>
- <action type="fix" dev="ggregory" due-to="Gary Gregory">[GZip] GzipCompressorInputStream now throws CompressorException instead of IllegalArgumetException/IllegalStateException.</action>
+ <action type="fix" dev="ggregory" due-to="Gary Gregory, KALI 834X">[GZip] GzipCompressorInputStream now throws CompressorException instead of IllegalArgumetException/IllegalStateException.</action>
<!-- FIX snappy -->
<action type="fix" dev="ggregory" due-to="Stanislav Fort, Gary Gregory">[Snappy] Fix for when a valid raw Snappy stream with uncompressed size > 2 GiB used to decompress and then fail at physical EOF with a “Premature end of stream” exception instead of completing cleanly.</action>
<!-- FIX deflate64 -->
diff --git a/src/main/java/org/apache/commons/compress/compressors/gzip/GzipParameters.java b/src/main/java/org/apache/commons/compress/compressors/gzip/GzipParameters.java
index d02ff11cf..eed5a87cf 100644
--- a/src/main/java/org/apache/commons/compress/compressors/gzip/GzipParameters.java
+++ b/src/main/java/org/apache/commons/compress/compressors/gzip/GzipParameters.java
@@ -26,6 +26,7 @@
import java.util.zip.Deflater;
import org.apache.commons.compress.CompressException;
+import org.apache.commons.compress.compressors.CompressorException;
import org.apache.commons.io.Charsets;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
@@ -509,9 +510,9 @@ public int hashCode() {
operatingSystem, trailerCrc, trailerISize);
}
- private String requireNonNulByte(final String text) {
+ private String requireNonNulByte(final String text) throws CompressorException {
if (StringUtils.isNotEmpty(text) && ArrayUtils.contains(text.getBytes(fileNameCharset), (byte) 0)) {
- throw new IllegalArgumentException("String encoded in Charset '" + fileNameCharset + "' contains the nul byte 0 which is not supported in gzip.");
+ throw new CompressorException("String encoded in Charset '" + fileNameCharset + "' contains the nul byte 0 which is not supported in gzip.");
}
return text;
}
@@ -534,9 +535,9 @@ public void setBufferSize(final int bufferSize) {
* Sets an arbitrary user-defined comment.
*
* @param comment A user-defined comment.
- * @throws IllegalArgumentException if the encoded bytes would contain a nul byte '\0' reserved for gzip field termination.
+ * @throws CompressorException if the encoded bytes would contain a nul byte '\0' reserved for gzip field termination.
*/
- public void setComment(final String comment) {
+ public void setComment(final String comment) throws CompressorException {
this.comment = requireNonNulByte(comment);
}
@@ -586,11 +587,11 @@ void setExtraFieldXlen(final int extraFieldXlen) {
* Sets the name of the compressed file.
*
* @param fileName The name of the file without the directory path.
- * @throws IllegalArgumentException if the encoded bytes would contain a nul byte '\0' reserved for gzip field termination.
+ * @throws CompressorException if the encoded bytes would contain a nul byte '\0' reserved for gzip field termination.
* @deprecated Use {@link #setFileName(String)}.
*/
@Deprecated
- public void setFilename(final String fileName) {
+ public void setFilename(final String fileName) throws CompressorException {
setFileName(fileName);
}
@@ -598,9 +599,9 @@ public void setFilename(final String fileName) {
* Sets the name of the compressed file.
*
* @param fileName The name of the file without the directory path.
- * @throws IllegalArgumentException if the encoded bytes would contain a nul byte '\0' reserved for gzip field termination.
+ * @throws CompressorException if the encoded bytes would contain a nul byte '\0' reserved for gzip field termination.
*/
- public void setFileName(final String fileName) {
+ public void setFileName(final String fileName) throws CompressorException {
this.fileName = requireNonNulByte(fileName);
}
diff --git a/src/test/java/org/apache/commons/compress/compressors/gzip/GzipCompressorInputStreamTest.java b/src/test/java/org/apache/commons/compress/compressors/gzip/GzipCompressorInputStreamTest.java
index 67301ec88..4b218a147 100644
--- a/src/test/java/org/apache/commons/compress/compressors/gzip/GzipCompressorInputStreamTest.java
+++ b/src/test/java/org/apache/commons/compress/compressors/gzip/GzipCompressorInputStreamTest.java
@@ -21,10 +21,14 @@
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -35,9 +39,13 @@
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.zip.CRC32;
+import java.util.zip.Deflater;
+import java.util.zip.DeflaterOutputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
+import org.apache.commons.compress.compressors.CompressorException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.file.PathUtils;
import org.apache.commons.io.function.IOStream;
@@ -353,4 +361,54 @@ void testReadGzipFileCreatedByCli() throws IOException {
}
}
+ private static byte[] gzipMemberWithFileName(final byte[] fileNameField) throws IOException {
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ bos.write(0x1f);
+ bos.write(0x8b); // magic
+ bos.write(0x08); // deflate
+ bos.write(0x08); // FLG: FNAME present
+ bos.write(new byte[] { 0, 0, 0, 0 }); // MTIME
+ bos.write(0x00); // XFL
+ bos.write(0xff); // OS unknown
+ bos.write(fileNameField);
+ bos.write(0x00); // NUL terminator for FNAME
+ final ByteArrayOutputStream deflated = new ByteArrayOutputStream();
+ try (DeflaterOutputStream dos = new DeflaterOutputStream(deflated, new Deflater(Deflater.DEFAULT_COMPRESSION, true))) {
+ // empty payload
+ }
+ bos.write(deflated.toByteArray());
+ final long crc = new CRC32().getValue();
+ bos.write((int) (crc & 0xff));
+ bos.write((int) (crc >> 8 & 0xff));
+ bos.write((int) (crc >> 16 & 0xff));
+ bos.write((int) (crc >> 24 & 0xff));
+ bos.write(new byte[] { 0, 0, 0, 0 }); // ISIZE
+ return bos.toByteArray();
+ }
+
+ /**
+ * A member whose FNAME field cannot be round-tripped through the configured charset must fail with a CompressorException rather than a raw
+ * IllegalArgumentException escaping the IOException contract of read().
+ */
+ @Test
+ void testUnencodableFileNameThrowsCompressorException() throws IOException {
+ // Under UTF-32BE a single stray byte decodes to U+FFFD, which re-encodes to bytes containing a NUL.
+ final byte[] gz = gzipMemberWithFileName(new byte[] { 0x41 });
+ assertThrows(CompressorException.class, () -> {
+ try (GzipCompressorInputStream gis = GzipCompressorInputStream.builder()
+ .setInputStream(new ByteArrayInputStream(gz))
+ .setFileNameCharset(Charset.forName("UTF-32BE"))
+ .get()) {
+ IOUtils.toString(gis, StandardCharsets.ISO_8859_1);
+ }
+ });
+ // A member that round-trips cleanly still parses.
+ final byte[] ok = gzipMemberWithFileName("name.txt".getBytes(StandardCharsets.ISO_8859_1));
+ try (GzipCompressorInputStream gis = GzipCompressorInputStream.builder()
+ .setInputStream(new ByteArrayInputStream(ok))
+ .get()) {
+ assertEquals("", IOUtils.toString(gis, StandardCharsets.ISO_8859_1));
+ assertEquals("name.txt", gis.getMetaData().getFileName());
+ }
+ }
}
diff --git a/src/test/java/org/apache/commons/compress/compressors/gzip/GzipParametersTest.java b/src/test/java/org/apache/commons/compress/compressors/gzip/GzipParametersTest.java
index ecc5a466b..3d7194ed6 100644
--- a/src/test/java/org/apache/commons/compress/compressors/gzip/GzipParametersTest.java
+++ b/src/test/java/org/apache/commons/compress/compressors/gzip/GzipParametersTest.java
@@ -30,6 +30,7 @@
import java.util.zip.Deflater;
import org.apache.commons.compress.CompressException;
+import org.apache.commons.compress.compressors.CompressorException;
import org.apache.commons.compress.compressors.gzip.GzipParameters.OS;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
@@ -91,11 +92,11 @@ void testIllegalCommentOrFileName(final Charset charset, final String text) {
final GzipParameters gzipParameters = new GzipParameters();
// null resets to default value
gzipParameters.setFileNameCharset(charset);
- assertThrows(IllegalArgumentException.class, () -> gzipParameters.setComment(text));
+ assertThrows(CompressorException.class, () -> gzipParameters.setComment(text));
assertNull(gzipParameters.getComment());
- assertThrows(IllegalArgumentException.class, () -> gzipParameters.setFilename(text));
+ assertThrows(CompressorException.class, () -> gzipParameters.setFilename(text));
assertNull(gzipParameters.getFileName());
- assertThrows(IllegalArgumentException.class, () -> gzipParameters.setFileName(text));
+ assertThrows(CompressorException.class, () -> gzipParameters.setFileName(text));
assertNull(gzipParameters.getFileName());
assertEquals(gzipParameters, gzipParameters);
}
@@ -111,7 +112,7 @@ void testIllegalCommentOrFileName(final Charset charset, final String text) {
"UTF-8 , helloéworld"
})
// @formatter:on
- void testLegalCommentOrFileName(final Charset charset, final String text) {
+ void testLegalCommentOrFileName(final Charset charset, final String text) throws CompressorException {
final GzipParameters gzipParameters = new GzipParameters();
// null resets to default value
gzipParameters.setFileNameCharset(charset);
(commons-compress) 01/02: Move action to its proper section.
Posted by gg...@apache.org.
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
commit 9b613b8b13ff850ec10b2cd12daa4f643951e5da
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Sun Aug 16 10:35:14 2026 -0400
Move action to its proper section.
---
src/changes/changes.xml | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 5c3f720f2..3ab6c4fe2 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -149,6 +149,7 @@ The <action> type attribute can be add,update,fix,remove.
<!-- FIX gzip -->
<action type="fix" dev="ggregory" due-to="Gary Gregory">[GZip] GzipParameters.setOperatingSystem(int) now throws CompressorException on illegal input.</action>
<action type="fix" issue="COMPRESS-705" dev="ggregory" due-to="Mario Fredenhagen, Gary Gregory">[GZip] GZip IOException: Extra subfield length exceeds remaining bytes in extra field; use new option GzipCompressorInputStream.Builder.setIgnoreExtraField(boolean).</action>
+ <action type="fix" dev="ggregory" due-to="Gary Gregory">[GZip] GzipCompressorInputStream now throws CompressorException instead of IllegalArgumetException/IllegalStateException.</action>
<!-- FIX snappy -->
<action type="fix" dev="ggregory" due-to="Stanislav Fort, Gary Gregory">[Snappy] Fix for when a valid raw Snappy stream with uncompressed size > 2 GiB used to decompress and then fail at physical EOF with a “Premature end of stream” exception instead of completing cleanly.</action>
<!-- FIX deflate64 -->
@@ -161,8 +162,6 @@ The <action> type attribute can be add,update,fix,remove.
<action type="fix" dev="ggregory" due-to="Gary Gregory">[LZ77] LZ77Compressor.prefill(byte[]) now throws CompressorException instead of IllegalArgumetException/IllegalStateException.</action>
<!-- FIX lz4 -->
<action type="fix" dev="ggregory" due-to="Gary Gregory">[LZ4] BlockLZ4CompressorOutputStream now throws CompressorException instead of IllegalArgumetException/IllegalStateException.</action>
- <!-- FIX gzip -->
- <action type="fix" dev="ggregory" due-to="Gary Gregory">[GZip] GzipCompressorInputStream now throws CompressorException instead of IllegalArgumetException/IllegalStateException.</action>
<!-- FIX lzw -->
<action type="fix" dev="ggregory" due-to="Gary Gregory">[LZW] LZWInputStream now throws CompressorException instead of IllegalArgumetException/IllegalStateException.</action>
<!-- FIX general -->