This is an automated email from the ASF dual-hosted git repository. ggregory 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 632434ccb Throw an IllegalArgumentException when a file name or comment in gzip parameters encodes to a byte array with a 0 byte (#618) 632434ccb is described below commit 632434ccbede8b2bd2e0a5bb3ff04844ced8355b Author: ddeschenes-1 <54910444+ddeschene...@users.noreply.github.com> AuthorDate: Sat Nov 30 08:23:06 2024 -0500 Throw an IllegalArgumentException when a file name or comment in gzip parameters encodes to a byte array with a 0 byte (#618) * (doc) Added safety check to avoid corrupting byte '0' in filename or comment of gzip parameters. * Remove unnecessary commas; normalize formatting * Collapse double `if` into a single `if` (and reuse isNotEmpty()) --------- Co-authored-by: Danny Deschenes <ddesche...@towerlogic.com> Co-authored-by: Gary Gregory <garydgreg...@users.noreply.github.com> --- .../compress/compressors/gzip/GzipParameters.java | 19 ++++++++-- .../compressors/gzip/GzipParametersTest.java | 44 ++++++++++++++++++++++ 2 files changed, 59 insertions(+), 4 deletions(-) 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 07ce38f26..4588e8ad9 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 @@ -25,7 +25,8 @@ import java.time.Instant; import java.util.zip.Deflater; import org.apache.commons.io.Charsets; - +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; /** * Parameters for the GZIP compressor. @@ -298,6 +299,13 @@ public class GzipParameters { private int bufferSize = 512; private int deflateStrategy = Deflater.DEFAULT_STRATEGY; + private String requireNonNulByte(final String text) { + 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."); + } + return text; + } + /** * Gets size of the buffer used to retrieve compressed data. * @@ -448,9 +456,10 @@ public class GzipParameters { * 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. */ public void setComment(final String comment) { - this.comment = comment; + this.comment = requireNonNulByte(comment); } /** @@ -495,20 +504,22 @@ public class GzipParameters { * 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. * @deprecated Use {@link #setFileName(String)}. */ @Deprecated public void setFilename(final String fileName) { - this.fileName = fileName; + setFileName(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. */ public void setFileName(final String fileName) { - this.fileName = fileName; + this.fileName = requireNonNulByte(fileName); } /** 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 30f1b09a9..d2febb1d9 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 @@ -20,11 +20,15 @@ package org.apache.commons.compress.compressors.gzip; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.nio.charset.Charset; import java.util.zip.Deflater; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; /** * Tests {@link GzipParameters}. @@ -46,4 +50,44 @@ public class GzipParametersTest { gzipParameters.setOS(GzipParameters.OS.Z_SYSTEM); assertTrue(gzipParameters.toString().contains("Z_SYSTEM")); } + + @ParameterizedTest + //@formatter:off + @CsvSource({ + " , helloworld", + " , helloéworld", + "ISO-8859-1, helloworld", + "ISO-8859-1, helloéworld", + "UTF-8 , helloworld", + "UTF-8 , helloéworld" + }) + //@formatter:on + public void testLegalCommentOrFileName(final String charset, final String text) { + final GzipParameters p = new GzipParameters(); + if (charset != null) { + p.setFileNameCharset(Charset.forName(charset)); + } + p.setComment(text); + p.setFilename(text); + p.setFileName(text); + } + + @ParameterizedTest + //@formatter:off + @CsvSource({ + " , hello\0world, false", + "ISO-8859-1, hello\0world, false", + "UTF-8 , hello\0world, false", + "UTF-16BE , helloworld, false" + }) + //@formatter:on + public void testIllegalCommentOrFileName(final String charset, final String text) { + final GzipParameters p = new GzipParameters(); + if (charset != null) { + p.setFileNameCharset(Charset.forName(charset)); + } + assertThrows(IllegalArgumentException.class, () -> p.setComment(text)); + assertThrows(IllegalArgumentException.class, () -> p.setFilename(text)); + assertThrows(IllegalArgumentException.class, () -> p.setFileName(text)); + } }