Skip to content

Commit 632434c

Browse files
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 <[email protected]> Co-authored-by: Gary Gregory <[email protected]>
1 parent c38b9f7 commit 632434c

File tree

2 files changed

+59
-4
lines changed

2 files changed

+59
-4
lines changed

src/main/java/org/apache/commons/compress/compressors/gzip/GzipParameters.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
import java.util.zip.Deflater;
2626

2727
import org.apache.commons.io.Charsets;
28-
28+
import org.apache.commons.lang3.ArrayUtils;
29+
import org.apache.commons.lang3.StringUtils;
2930

3031
/**
3132
* Parameters for the GZIP compressor.
@@ -298,6 +299,13 @@ public int type() {
298299
private int bufferSize = 512;
299300
private int deflateStrategy = Deflater.DEFAULT_STRATEGY;
300301

302+
private String requireNonNulByte(final String text) {
303+
if (StringUtils.isNotEmpty(text) && ArrayUtils.contains(text.getBytes(fileNameCharset), (byte) 0)) {
304+
throw new IllegalArgumentException("String encoded in Charset '" + fileNameCharset + "' contains the nul byte 0 which is not supported in gzip.");
305+
}
306+
return text;
307+
}
308+
301309
/**
302310
* Gets size of the buffer used to retrieve compressed data.
303311
*
@@ -448,9 +456,10 @@ public void setBufferSize(final int bufferSize) {
448456
* Sets an arbitrary user-defined comment.
449457
*
450458
* @param comment a user-defined comment.
459+
* @throws IllegalArgumentException if the encoded bytes would contain a nul byte '\0' reserved for gzip field termination.
451460
*/
452461
public void setComment(final String comment) {
453-
this.comment = comment;
462+
this.comment = requireNonNulByte(comment);
454463
}
455464

456465
/**
@@ -495,20 +504,22 @@ public void setExtraField(final ExtraField extra) {
495504
* Sets the name of the compressed file.
496505
*
497506
* @param fileName the name of the file without the directory path
507+
* @throws IllegalArgumentException if the encoded bytes would contain a nul byte '\0' reserved for gzip field termination.
498508
* @deprecated Use {@link #setFileName(String)}.
499509
*/
500510
@Deprecated
501511
public void setFilename(final String fileName) {
502-
this.fileName = fileName;
512+
setFileName(fileName);
503513
}
504514

505515
/**
506516
* Sets the name of the compressed file.
507517
*
508518
* @param fileName the name of the file without the directory path
519+
* @throws IllegalArgumentException if the encoded bytes would contain a nul byte '\0' reserved for gzip field termination.
509520
*/
510521
public void setFileName(final String fileName) {
511-
this.fileName = fileName;
522+
this.fileName = requireNonNulByte(fileName);
512523
}
513524

514525
/**

src/test/java/org/apache/commons/compress/compressors/gzip/GzipParametersTest.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,15 @@
2020
package org.apache.commons.compress.compressors.gzip;
2121

2222
import static org.junit.jupiter.api.Assertions.assertEquals;
23+
import static org.junit.jupiter.api.Assertions.assertThrows;
2324
import static org.junit.jupiter.api.Assertions.assertTrue;
2425

26+
import java.nio.charset.Charset;
2527
import java.util.zip.Deflater;
2628

2729
import org.junit.jupiter.api.Test;
30+
import org.junit.jupiter.params.ParameterizedTest;
31+
import org.junit.jupiter.params.provider.CsvSource;
2832

2933
/**
3034
* Tests {@link GzipParameters}.
@@ -46,4 +50,44 @@ public void testToString() {
4650
gzipParameters.setOS(GzipParameters.OS.Z_SYSTEM);
4751
assertTrue(gzipParameters.toString().contains("Z_SYSTEM"));
4852
}
53+
54+
@ParameterizedTest
55+
//@formatter:off
56+
@CsvSource({
57+
" , helloworld",
58+
" , helloéworld",
59+
"ISO-8859-1, helloworld",
60+
"ISO-8859-1, helloéworld",
61+
"UTF-8 , helloworld",
62+
"UTF-8 , helloéworld"
63+
})
64+
//@formatter:on
65+
public void testLegalCommentOrFileName(final String charset, final String text) {
66+
final GzipParameters p = new GzipParameters();
67+
if (charset != null) {
68+
p.setFileNameCharset(Charset.forName(charset));
69+
}
70+
p.setComment(text);
71+
p.setFilename(text);
72+
p.setFileName(text);
73+
}
74+
75+
@ParameterizedTest
76+
//@formatter:off
77+
@CsvSource({
78+
" , hello\0world, false",
79+
"ISO-8859-1, hello\0world, false",
80+
"UTF-8 , hello\0world, false",
81+
"UTF-16BE , helloworld, false"
82+
})
83+
//@formatter:on
84+
public void testIllegalCommentOrFileName(final String charset, final String text) {
85+
final GzipParameters p = new GzipParameters();
86+
if (charset != null) {
87+
p.setFileNameCharset(Charset.forName(charset));
88+
}
89+
assertThrows(IllegalArgumentException.class, () -> p.setComment(text));
90+
assertThrows(IllegalArgumentException.class, () -> p.setFilename(text));
91+
assertThrows(IllegalArgumentException.class, () -> p.setFileName(text));
92+
}
4993
}

0 commit comments

Comments
 (0)