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 adda4c182 COMPRESS-632: Fixes for CPIO bugs (#441)
adda4c182 is described below
commit adda4c1829aaae45939e370f47b478ef7f3e7e33
Author: Yakov Shafranovich <[email protected]>
AuthorDate: Tue Dec 5 13:55:50 2023 -0500
COMPRESS-632: Fixes for CPIO bugs (#441)
* Fixes for CPIO bugs
* Fixes
* fixed formatting
* fixing checkstyle
* moving overflow check to utility class
* added unit test
* made variables final
* refactor Integer and Long parsing
* split the methods into two: with and without radix
* minor refactoring
* changed test assertions
---
.../archivers/ar/ArArchiveInputStream.java | 30 +++-----
.../archivers/cpio/CpioArchiveInputStream.java | 3 +-
.../compress/archivers/tar/TarArchiveEntry.java | 27 +++----
.../commons/compress/archivers/tar/TarUtils.java | 22 +-----
.../harmony/pack200/NewAttributeBands.java | 3 +-
.../compress/harmony/pack200/Pack200Adapter.java | 14 +++-
.../harmony/pack200/Pack200PackerAdapter.java | 7 +-
.../harmony/unpack200/NewAttributeBands.java | 3 +-
.../apache/commons/compress/utils/ExactMath.java | 9 ++-
.../commons/compress/utils/ParsingUtils.java | 83 +++++++++++++++++++++
.../archivers/cpio/CpioArchiveEntryTest.java} | 32 +++-----
.../archivers/cpio/CpioArchiveInputStreamTest.java | 10 +++
.../commons/compress/utils/ExactMathTest.java | 31 ++++++++
.../commons/compress/utils/ParsingUtilsTest.java | 59 +++++++++++++++
.../commons/compress/cpio/bad_long_value.cpio | Bin 0 -> 1536 bytes
15 files changed, 244 insertions(+), 89 deletions(-)
diff --git
a/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java
b/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java
index 85d5144ad..d0f32954d 100644
---
a/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java
+++
b/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java
@@ -27,6 +27,7 @@ import java.util.regex.Pattern;
import org.apache.commons.compress.archivers.ArchiveInputStream;
import org.apache.commons.compress.utils.ArchiveUtils;
import org.apache.commons.compress.utils.IOUtils;
+import org.apache.commons.compress.utils.ParsingUtils;
/**
* Implements the "ar" archive format as an input stream.
@@ -152,28 +153,28 @@ public class ArArchiveInputStream extends
ArchiveInputStream<ArArchiveEntry> {
this.input = inputStream;
}
- private int asInt(final byte[] byteArray, final int offset, final int len)
{
+ private int asInt(final byte[] byteArray, final int offset, final int len)
throws IOException {
return asInt(byteArray, offset, len, 10, false);
}
- private int asInt(final byte[] byteArray, final int offset, final int len,
final boolean treatBlankAsZero) {
+ private int asInt(final byte[] byteArray, final int offset, final int len,
final boolean treatBlankAsZero) throws IOException {
return asInt(byteArray, offset, len, 10, treatBlankAsZero);
}
- private int asInt(final byte[] byteArray, final int offset, final int len,
final int base) {
+ private int asInt(final byte[] byteArray, final int offset, final int len,
final int base) throws IOException {
return asInt(byteArray, offset, len, base, false);
}
- private int asInt(final byte[] byteArray, final int offset, final int len,
final int base, final boolean treatBlankAsZero) {
+ private int asInt(final byte[] byteArray, final int offset, final int len,
final int base, final boolean treatBlankAsZero) throws IOException {
final String string = ArchiveUtils.toAsciiString(byteArray, offset,
len).trim();
if (string.isEmpty() && treatBlankAsZero) {
return 0;
}
- return Integer.parseInt(string, base);
+ return ParsingUtils.parseIntValue(string, base);
}
- private long asLong(final byte[] byteArray, final int offset, final int
len) {
- return Long.parseLong(ArchiveUtils.toAsciiString(byteArray, offset,
len).trim());
+ private long asLong(final byte[] byteArray, final int offset, final int
len) throws IOException {
+ return
ParsingUtils.parseLongValue(ArchiveUtils.toAsciiString(byteArray, offset,
len).trim());
}
/*
@@ -198,13 +199,7 @@ public class ArArchiveInputStream extends
ArchiveInputStream<ArArchiveEntry> {
* @since 1.3
*/
private String getBSDLongName(final String bsdLongName) throws IOException
{
- final int nameLen;
- try {
- nameLen =
Integer.parseInt(bsdLongName.substring(BSD_LONGNAME_PREFIX_LEN));
- } catch (NumberFormatException ex) {
- throw new IOException("Broken archive, unable to parse BSD long
name length field as a number", ex);
- }
-
+ final int nameLen =
ParsingUtils.parseIntValue(bsdLongName.substring(BSD_LONGNAME_PREFIX_LEN));
final byte[] name = IOUtils.readRange(input, nameLen);
final int read = name.length;
trackReadBytes(read);
@@ -326,12 +321,7 @@ public class ArArchiveInputStream extends
ArchiveInputStream<ArArchiveEntry> {
if (temp.endsWith("/")) { // GNU terminator
temp = temp.substring(0, temp.length() - 1);
} else if (isGNULongName(temp)) {
- int off;
- try {
- off = Integer.parseInt(temp.substring(1));// get the offset
- } catch (NumberFormatException ex) {
- throw new IOException("Broken archive, unable to parse GNU
long name offset field as a number", ex);
- }
+ final int off = ParsingUtils.parseIntValue(temp.substring(1));//
get the offset
temp = getExtendedName(off); // convert to the long name
} else if (isBSDLongName(temp)) {
temp = getBSDLongName(temp);
diff --git
a/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStream.java
b/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStream.java
index 0e17d3202..42898831a 100644
---
a/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStream.java
+++
b/src/main/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStream.java
@@ -28,6 +28,7 @@ import
org.apache.commons.compress.archivers.zip.ZipEncodingHelper;
import org.apache.commons.compress.utils.ArchiveUtils;
import org.apache.commons.compress.utils.CharsetNames;
import org.apache.commons.compress.utils.IOUtils;
+import org.apache.commons.compress.utils.ParsingUtils;
/**
* CpioArchiveInputStream is a stream for reading cpio streams. All formats of
cpio are supported (old ascii, old binary, new portable format and the new
@@ -362,7 +363,7 @@ public class CpioArchiveInputStream extends
ArchiveInputStream<CpioArchiveEntry>
private long readAsciiLong(final int length, final int radix) throws
IOException {
final byte[] tmpBuffer = readRange(length);
- return Long.parseLong(ArchiveUtils.toAsciiString(tmpBuffer), radix);
+ return
ParsingUtils.parseLongValue(ArchiveUtils.toAsciiString(tmpBuffer), radix);
}
private long readBinaryLong(final int length, final boolean swapHalfWord)
throws IOException {
diff --git
a/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveEntry.java
b/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveEntry.java
index e9e94000b..02b4ed449 100644
---
a/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveEntry.java
+++
b/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveEntry.java
@@ -50,6 +50,7 @@ import
org.apache.commons.compress.archivers.EntryStreamOffsets;
import org.apache.commons.compress.archivers.zip.ZipEncoding;
import org.apache.commons.compress.utils.ArchiveUtils;
import org.apache.commons.compress.utils.IOUtils;
+import org.apache.commons.compress.utils.ParsingUtils;
import org.apache.commons.compress.utils.TimeUtils;
/**
@@ -759,9 +760,9 @@ public class TarArchiveEntry implements ArchiveEntry,
TarConstants, EntryStreamO
return fill((byte) value, offset, outbuf, length);
}
- void fillGNUSparse0xData(final Map<String, String> headers) {
+ void fillGNUSparse0xData(final Map<String, String> headers) throws
IOException {
paxGNUSparse = true;
- realSize = Integer.parseInt(headers.get(TarGnuSparseKeys.SIZE));
+ realSize =
ParsingUtils.parseIntValue(headers.get(TarGnuSparseKeys.SIZE));
if (headers.containsKey(TarGnuSparseKeys.NAME)) {
// version 0.1
name = headers.get(TarGnuSparseKeys.NAME);
@@ -775,22 +776,14 @@ public class TarArchiveEntry implements ArchiveEntry,
TarConstants, EntryStreamO
name = headers.get(TarGnuSparseKeys.NAME);
}
if (headers.containsKey(TarGnuSparseKeys.REALSIZE)) {
- try {
- realSize =
Integer.parseInt(headers.get(TarGnuSparseKeys.REALSIZE));
- } catch (final NumberFormatException ex) {
- throw new IOException("Corrupted TAR archive.
GNU.sparse.realsize header for " + name + " contains non-numeric value");
- }
+ realSize =
ParsingUtils.parseIntValue(headers.get(TarGnuSparseKeys.REALSIZE));
}
}
void fillStarSparseData(final Map<String, String> headers) throws
IOException {
starSparse = true;
if (headers.containsKey("SCHILY.realsize")) {
- try {
- realSize = Long.parseLong(headers.get("SCHILY.realsize"));
- } catch (final NumberFormatException ex) {
- throw new IOException("Corrupted TAR archive. SCHILY.realsize
header for " + name + " contains non-numeric value");
- }
+ realSize =
ParsingUtils.parseLongValue(headers.get("SCHILY.realsize"));
}
}
@@ -1634,19 +1627,19 @@ public class TarArchiveEntry implements ArchiveEntry,
TarConstants, EntryStreamO
setLinkName(val);
break;
case "gid":
- setGroupId(Long.parseLong(val));
+ setGroupId(ParsingUtils.parseLongValue(val));
break;
case "gname":
setGroupName(val);
break;
case "uid":
- setUserId(Long.parseLong(val));
+ setUserId(ParsingUtils.parseLongValue(val));
break;
case "uname":
setUserName(val);
break;
case "size":
- final long size = Long.parseLong(val);
+ final long size = ParsingUtils.parseLongValue(val);
if (size < 0) {
throw new IOException("Corrupted TAR archive. Entry size is
negative");
}
@@ -1665,14 +1658,14 @@ public class TarArchiveEntry implements ArchiveEntry,
TarConstants, EntryStreamO
setCreationTime(FileTime.from(parseInstantFromDecimalSeconds(val)));
break;
case "SCHILY.devminor":
- final int devMinor = Integer.parseInt(val);
+ final int devMinor = ParsingUtils.parseIntValue(val);
if (devMinor < 0) {
throw new IOException("Corrupted TAR archive. Dev-Minor is
negative");
}
setDevMinor(devMinor);
break;
case "SCHILY.devmajor":
- final int devMajor = Integer.parseInt(val);
+ final int devMajor = ParsingUtils.parseIntValue(val);
if (devMajor < 0) {
throw new IOException("Corrupted TAR archive. Dev-Major is
negative");
}
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 4c3741776..ef4538ee4 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
@@ -36,6 +36,7 @@ import org.apache.commons.compress.archivers.zip.ZipEncoding;
import org.apache.commons.compress.archivers.zip.ZipEncodingHelper;
import org.apache.commons.compress.utils.CharsetNames;
import org.apache.commons.compress.utils.IOUtils;
+import org.apache.commons.compress.utils.ParsingUtils;
/**
* This class provides static utility methods to work with byte streams.
@@ -396,21 +397,11 @@ public class TarUtils {
}
for (int i = 0; i < sparseHeaderStrings.length; i += 2) {
- long sparseOffset;
- try {
- sparseOffset = Long.parseLong(sparseHeaderStrings[i]);
- } catch (final NumberFormatException ex) {
- throw new IOException("Corrupted TAR archive." + " Sparse
struct offset contains a non-numeric value");
- }
+ final long sparseOffset =
ParsingUtils.parseLongValue(sparseHeaderStrings[i]);
if (sparseOffset < 0) {
throw new IOException("Corrupted TAR archive." + " Sparse
struct offset contains negative value");
}
- long sparseNumbytes;
- try {
- sparseNumbytes = Long.parseLong(sparseHeaderStrings[i + 1]);
- } catch (final NumberFormatException ex) {
- throw new IOException("Corrupted TAR archive." + " Sparse
struct numbytes contains a non-numeric value");
- }
+ final long sparseNumbytes =
ParsingUtils.parseLongValue(sparseHeaderStrings[i + 1]);
if (sparseNumbytes < 0) {
throw new IOException("Corrupted TAR archive." + " Sparse
struct numbytes contains negative value");
}
@@ -750,12 +741,7 @@ public class TarUtils {
throw new IOException(
"Failed to read Paxheader." +
TarGnuSparseKeys.OFFSET + " is expected before GNU.sparse.numbytes shows up.");
}
- long numbytes;
- try {
- numbytes = Long.parseLong(value);
- } catch (final NumberFormatException ex) {
- throw new IOException("Failed to read
Paxheader." + TarGnuSparseKeys.NUMBYTES + " contains a non-numeric value.");
- }
+ final long numbytes =
ParsingUtils.parseLongValue(value);
if (numbytes < 0) {
throw new IOException("Failed to read
Paxheader." + TarGnuSparseKeys.NUMBYTES + " contains negative value");
}
diff --git
a/src/main/java/org/apache/commons/compress/harmony/pack200/NewAttributeBands.java
b/src/main/java/org/apache/commons/compress/harmony/pack200/NewAttributeBands.java
index 6dc17e85a..46c06fc8d 100644
---
a/src/main/java/org/apache/commons/compress/harmony/pack200/NewAttributeBands.java
+++
b/src/main/java/org/apache/commons/compress/harmony/pack200/NewAttributeBands.java
@@ -28,6 +28,7 @@ import java.util.List;
import java.util.Map;
import
org.apache.commons.compress.harmony.pack200.AttributeDefinitionBands.AttributeDefinition;
+import org.apache.commons.compress.utils.ParsingUtils;
import org.objectweb.asm.Label;
/**
@@ -824,7 +825,7 @@ public class NewAttributeBands extends BandSet {
if (read != digits.length) {
throw new IOException("Error reading from the input stream");
}
- return Integer.valueOf(Integer.parseInt((negative ? "-" : "") + new
String(digits)));
+ return ParsingUtils.parseIntValue((negative ? "-" : "") + new
String(digits));
}
/**
diff --git
a/src/main/java/org/apache/commons/compress/harmony/pack200/Pack200Adapter.java
b/src/main/java/org/apache/commons/compress/harmony/pack200/Pack200Adapter.java
index 44471ed9e..1f53117be 100644
---
a/src/main/java/org/apache/commons/compress/harmony/pack200/Pack200Adapter.java
+++
b/src/main/java/org/apache/commons/compress/harmony/pack200/Pack200Adapter.java
@@ -18,6 +18,7 @@ package org.apache.commons.compress.harmony.pack200;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
+import java.io.IOException;
import java.util.SortedMap;
import java.util.TreeMap;
@@ -40,12 +41,21 @@ public abstract class Pack200Adapter {
* Completion between 0..1.
*
* @param value Completion between 0..1.
+ * @throws IOException if the value cannot be parsed
*/
- protected void completed(final double value) {
+ protected void completed(final double value) throws IOException {
firePropertyChange("pack.progress", null, String.valueOf((int) (100 *
value))); //$NON-NLS-1$
}
- protected void firePropertyChange(final String propertyName, final Object
oldValue, final Object newValue) {
+ /**
+ * Reports a property update to listeners
+ *
+ * @param propertyName name of property being updated
+ * @param oldValue old property value
+ * @param newValue new property value
+ * @throws IOException if the values cannot be parsed
+ */
+ protected void firePropertyChange(final String propertyName, final Object
oldValue, final Object newValue) throws IOException {
support.firePropertyChange(propertyName, oldValue, newValue);
}
diff --git
a/src/main/java/org/apache/commons/compress/harmony/pack200/Pack200PackerAdapter.java
b/src/main/java/org/apache/commons/compress/harmony/pack200/Pack200PackerAdapter.java
index c4723368f..8e5debe65 100644
---
a/src/main/java/org/apache/commons/compress/harmony/pack200/Pack200PackerAdapter.java
+++
b/src/main/java/org/apache/commons/compress/harmony/pack200/Pack200PackerAdapter.java
@@ -22,6 +22,7 @@ import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
import org.apache.commons.compress.java.util.jar.Pack200.Packer;
+import org.apache.commons.compress.utils.ParsingUtils;
/**
* This class provides the binding between the standard Pack200 interface and
the internal interface for (un)packing. As this uses generics for the SortedMap,
@@ -32,7 +33,7 @@ public class Pack200PackerAdapter extends Pack200Adapter
implements Packer {
private final PackingOptions options = new PackingOptions();
@Override
- protected void firePropertyChange(final String propertyName, final Object
oldValue, final Object newValue) {
+ protected void firePropertyChange(final String propertyName, final Object
oldValue, final Object newValue) throws IOException {
super.firePropertyChange(propertyName, oldValue, newValue);
if (newValue != null && !newValue.equals(oldValue)) {
if (propertyName.startsWith(CLASS_ATTRIBUTE_PFX)) {
@@ -44,7 +45,7 @@ public class Pack200PackerAdapter extends Pack200Adapter
implements Packer {
} else if (propertyName.equals(DEFLATE_HINT)) {
options.setDeflateHint((String) newValue);
} else if (propertyName.equals(EFFORT)) {
- options.setEffort(Integer.parseInt((String) newValue));
+ options.setEffort(ParsingUtils.parseIntValue((String)
newValue));
} else if (propertyName.startsWith(FIELD_ATTRIBUTE_PFX)) {
final String attributeName =
propertyName.substring(FIELD_ATTRIBUTE_PFX.length());
options.addFieldAttributeAction(attributeName, (String)
newValue);
@@ -61,7 +62,7 @@ public class Pack200PackerAdapter extends Pack200Adapter
implements Packer {
}
options.addPassFile((String) newValue);
} else if (propertyName.equals(SEGMENT_LIMIT)) {
- options.setSegmentLimit(Long.parseLong((String) newValue));
+ options.setSegmentLimit(ParsingUtils.parseLongValue((String)
newValue));
} else if (propertyName.equals(UNKNOWN_ATTRIBUTE)) {
options.setUnknownAttributeAction((String) newValue);
}
diff --git
a/src/main/java/org/apache/commons/compress/harmony/unpack200/NewAttributeBands.java
b/src/main/java/org/apache/commons/compress/harmony/unpack200/NewAttributeBands.java
index bca63fd98..cc0a339dc 100644
---
a/src/main/java/org/apache/commons/compress/harmony/unpack200/NewAttributeBands.java
+++
b/src/main/java/org/apache/commons/compress/harmony/unpack200/NewAttributeBands.java
@@ -39,6 +39,7 @@ import
org.apache.commons.compress.harmony.unpack200.bytecode.CPNameAndType;
import org.apache.commons.compress.harmony.unpack200.bytecode.CPString;
import org.apache.commons.compress.harmony.unpack200.bytecode.CPUTF8;
import org.apache.commons.compress.harmony.unpack200.bytecode.NewAttribute;
+import org.apache.commons.compress.utils.ParsingUtils;
/**
* Sets of bands relating to a non-predefined attribute
@@ -884,7 +885,7 @@ public class NewAttributeBands extends BandSet {
if (read != digits.length) {
throw new IOException("Error reading from the input stream");
}
- return Integer.valueOf(Integer.parseInt((negative ? "-" : "") + new
String(digits)));
+ return ParsingUtils.parseIntValue((negative ? "-" : "") + new
String(digits));
}
/**
diff --git a/src/main/java/org/apache/commons/compress/utils/ExactMath.java
b/src/main/java/org/apache/commons/compress/utils/ExactMath.java
index 579fd7517..6d72acd9a 100644
--- a/src/main/java/org/apache/commons/compress/utils/ExactMath.java
+++ b/src/main/java/org/apache/commons/compress/utils/ExactMath.java
@@ -32,11 +32,14 @@ public class ExactMath {
* @param x the first value, an int.
* @param y the second value, a long,
* @return the addition of both values.
- * @throws ArithmeticException when y overflow an int.
- * @throws ArithmeticException if the result overflows an int.
+ * @throws IllegalArgumentException when y or the result overflows an int
*/
public static int add(final int x, final long y) {
- return Math.addExact(x, Math.toIntExact(y));
+ try {
+ return Math.addExact(x, Math.toIntExact(y));
+ } catch (final ArithmeticException exp) {
+ throw new IllegalArgumentException("Argument too large or result
overflows", exp);
+ }
}
private ExactMath() {
diff --git a/src/main/java/org/apache/commons/compress/utils/ParsingUtils.java
b/src/main/java/org/apache/commons/compress/utils/ParsingUtils.java
new file mode 100644
index 000000000..0fc320209
--- /dev/null
+++ b/src/main/java/org/apache/commons/compress/utils/ParsingUtils.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.compress.utils;
+
+import java.io.IOException;
+
+/**
+ * Utility methods for parsing data and converting it to other formats.
+ *
+ * @since 1.26.0
+ */
+public final class ParsingUtils {
+ /**
+ * Parses the provided string value to an Integer, assuming a base-10 radix
+ *
+ * @param value string value to parse
+ * @return parsed value as an int
+ * @throws IOException when the value cannot be parsed
+ */
+ public static int parseIntValue(final String value) throws IOException {
+ return parseIntValue(value, 10);
+ }
+
+ /**
+ * Parse the provided string value to an Integer with a provided radix
+ *
+ * @param value string value to parse
+ * @param radix radix value to use for parsing
+ * @return parsed value as an int
+ * @throws IOException when the value cannot be parsed
+ */
+ public static int parseIntValue(final String value, final int radix)
throws IOException {
+ try {
+ return Integer.parseInt(value, radix);
+ } catch (final NumberFormatException exp) {
+ throw new IOException("Unable to parse int from string value: " +
value);
+ }
+ }
+
+ /**
+ * Parses the provided string value to a Long, assuming a base-10 radix
+ *
+ * @param value string value to parse
+ * @return parsed value as a long
+ * @throws IOException when the value cannot be parsed
+ */
+ public static long parseLongValue(final String value) throws IOException {
+ return parseLongValue(value, 10);
+ }
+
+ /**
+ * Parses the provided string value to a Long with a provided radix
+ *
+ * @param value string value to parse
+ * @param radix radix value to use for parsing
+ * @return parsed value as a long
+ * @throws IOException when the value cannot be parsed
+ */
+ public static long parseLongValue(final String value, final int radix)
throws IOException {
+ try {
+ return Long.parseLong(value, radix);
+ } catch (final NumberFormatException exp) {
+ throw new IOException("Unable to parse long from string value: " +
value);
+ }
+ }
+
+ private ParsingUtils() {
+ /* no instances */ }
+}
diff --git a/src/main/java/org/apache/commons/compress/utils/ExactMath.java
b/src/test/java/org/apache/commons/compress/archivers/cpio/CpioArchiveEntryTest.java
similarity index 53%
copy from src/main/java/org/apache/commons/compress/utils/ExactMath.java
copy to
src/test/java/org/apache/commons/compress/archivers/cpio/CpioArchiveEntryTest.java
index 579fd7517..8b5eb33c7 100644
--- a/src/main/java/org/apache/commons/compress/utils/ExactMath.java
+++
b/src/test/java/org/apache/commons/compress/archivers/cpio/CpioArchiveEntryTest.java
@@ -16,31 +16,17 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.commons.compress.archivers.cpio;
-package org.apache.commons.compress.utils;
+import static org.junit.Assert.assertThrows;
-/**
- * PRIVATE.
- *
- * Performs exact math through {@link Math} "exact" APIs.
- */
-public class ExactMath {
+import org.junit.jupiter.api.Test;
- /**
- * Returns the int result of adding an int and a long, and throws an
exception if the result overflows an int.
- *
- * @param x the first value, an int.
- * @param y the second value, a long,
- * @return the addition of both values.
- * @throws ArithmeticException when y overflow an int.
- * @throws ArithmeticException if the result overflows an int.
- */
- public static int add(final int x, final long y) {
- return Math.addExact(x, Math.toIntExact(y));
+public class CpioArchiveEntryTest {
+ @Test
+ public void testGetHeaderPadCountOverflow() throws Exception {
+ final CpioArchiveEntry entry = new
CpioArchiveEntry(CpioConstants.FORMAT_NEW);
+ entry.setName("test name");
+ assertThrows(IllegalArgumentException.class, () ->
entry.getHeaderPadCount(Long.MAX_VALUE));
}
-
- private ExactMath() {
- // no instances
- }
-
}
diff --git
a/src/test/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStreamTest.java
b/src/test/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStreamTest.java
index 9c0d712a0..6fb2ed6ef 100644
---
a/src/test/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStreamTest.java
+++
b/src/test/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStreamTest.java
@@ -20,7 +20,9 @@ package org.apache.commons.compress.archivers.cpio;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.compress.AbstractTest;
@@ -105,4 +107,12 @@ public class CpioArchiveInputStreamTest extends
AbstractTest {
}
}
+ @Test
+ public void testInvalidLongValueInMetadata() throws Exception {
+ try (InputStream in =
newInputStream("org/apache/commons/compress/cpio/bad_long_value.cpio");
+ CpioArchiveInputStream archive = new CpioArchiveInputStream(in)) {
+ assertThrows(IOException.class, archive::getNextEntry);
+ }
+ }
+
}
diff --git a/src/test/java/org/apache/commons/compress/utils/ExactMathTest.java
b/src/test/java/org/apache/commons/compress/utils/ExactMathTest.java
new file mode 100644
index 000000000..808a2cd93
--- /dev/null
+++ b/src/test/java/org/apache/commons/compress/utils/ExactMathTest.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.compress.utils;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.junit.jupiter.api.Test;
+
+public class ExactMathTest {
+
+ @Test
+ public void testOverflow() {
+ assertThrows(IllegalArgumentException.class, () -> ExactMath.add(1,
Long.MAX_VALUE / 1000));
+ assertThrows(IllegalArgumentException.class, () ->
ExactMath.add(Integer.MAX_VALUE, Integer.MAX_VALUE));
+ }
+
+}
diff --git
a/src/test/java/org/apache/commons/compress/utils/ParsingUtilsTest.java
b/src/test/java/org/apache/commons/compress/utils/ParsingUtilsTest.java
new file mode 100644
index 000000000..1800a6b7a
--- /dev/null
+++ b/src/test/java/org/apache/commons/compress/utils/ParsingUtilsTest.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.compress.utils;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.io.IOException;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+/**
+ * Unit tests for class {@link ParsingUtils}.
+ *
+ * @see ParsingUtils
+ */
+public class ParsingUtilsTest {
+
+ @ParameterizedTest
+ @ValueSource(strings = {Integer.MIN_VALUE + "1", "x.x", "9e999", "1.1",
"one", Integer.MAX_VALUE + "1"})
+ public void testParseIntValueInvalidValues(final String value) {
+ assertThrows(IOException.class, () ->
ParsingUtils.parseIntValue(value, 10));
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {Integer.MIN_VALUE + "", "-1", "1", "123456",
Integer.MAX_VALUE + ""})
+ public void testParseIntValueValidValues(final String value) throws
Exception {
+ assertEquals(Long.parseLong(value), ParsingUtils.parseIntValue(value,
10));
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {Long.MIN_VALUE + "1", "x.x", "9e999", "1.1",
"one", Long.MAX_VALUE + "1"})
+ public void testParseLongValueInvalidValues(final String value) {
+ assertThrows(IOException.class, () ->
ParsingUtils.parseLongValue(value, 10));
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {Long.MIN_VALUE + "", "-1", "1", "12345678901234",
Long.MAX_VALUE + ""})
+ public void testParseLongValueValidValues(final String value) throws
Exception {
+ assertEquals(Long.parseLong(value), ParsingUtils.parseLongValue(value,
10));
+ }
+
+}
diff --git
a/src/test/resources/org/apache/commons/compress/cpio/bad_long_value.cpio
b/src/test/resources/org/apache/commons/compress/cpio/bad_long_value.cpio
new file mode 100644
index 000000000..d497cd75c
Binary files /dev/null and
b/src/test/resources/org/apache/commons/compress/cpio/bad_long_value.cpio differ