This is an automated email from the ASF dual-hosted git repository. pkarwasz pushed a commit to branch fix/cpio-crc-verification in repository https://gitbox.apache.org/repos/asf/commons-compress.git
commit f4743334053d6fc4adeaa207dcddb8e2186f97cb Author: Piotr P. Karwasz <[email protected]> AuthorDate: Thu Oct 9 11:03:51 2025 +0200 [COMPRESS-711] Fix incorrect CPIO checksum verification This PR fixes an issue in `CpioArchiveInputStream` where the checksum was computed using the wrong slice of the buffer. Previously, it always used bytes `0` through `len`, ignoring the specified `off` parameter. As a result, checksum verification could fail when `read()` was called with a non-zero offset. ### Changes * Corrected checksum calculation to use the actual range `off` through `off + len`. * Added a regression test to ensure checksum verification works correctly with non-zero offsets. --- src/changes/changes.xml | 1 + .../compress/archivers/cpio/CpioArchiveInputStream.java | 4 ++-- .../archivers/cpio/CpioArchiveInputStreamTest.java | 17 +++++++++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 85c50ea00..63b00a316 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -89,6 +89,7 @@ The <action> type attribute can be add,update,fix,remove. <action type="fix" dev="ggregory" due-to="Stan, Gary Gregory">CpioArchiveInputStream.getNextEntry() now throws a MemoryLimitException instead of OutOfMemoryError when it can't process input greater than available memory.</action> <action type="fix" dev="ggregory" due-to="Gary Gregory">CpioArchiveInputStream.readOldAsciiEntry(boolean) now throws ArchiveException instead of Arithmetic exception.</action> <action type="fix" dev="ggregory" due-to="Gary Gregory">CpioArchiveInputStream.readOldBinaryEntry(boolean) now throws ArchiveException instead of Arithmetic exception.</action> + <action type="fix" issue="COMPRESS-711" dev="pkarwasz" due-to="Piotr P. Karwasz">Fix checksum calculation in CpioArchiveInputStream when reading with a non-zero offset.</action> <!-- FIX gzip --> <action type="fix" dev="ggregory" due-to="Gary Gregory">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 IOException: Extra subfield length exceeds remaining bytes in extra field; use new option GzipCompressorInputStream.Builder.setIgnoreExtraField(boolean).</action> 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 2ef00b7b5..2915bb448 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 @@ -404,9 +404,9 @@ public int read(final byte[] b, final int off, final int len) throws IOException final int tmpread = readFully(b, off, tmplength); if (entry.getFormat() == FORMAT_NEW_CRC) { for (int pos = 0; pos < tmpread; pos++) { - crc += b[pos] & 0xFF; - crc &= 0xFFFFFFFFL; + crc += b[off + pos] & 0xFF; } + crc &= 0xFFFFFFFFL; } if (tmpread > 0) { entryBytesRead += tmpread; 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 75cacb00f..ecdab8388 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 @@ -19,6 +19,7 @@ package org.apache.commons.compress.archivers.cpio; import static org.apache.commons.lang3.reflect.FieldUtils.readDeclaredField; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -33,6 +34,7 @@ import org.apache.commons.compress.archivers.ArchiveException; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.Test; +import org.junitpioneer.jupiter.Issue; class CpioArchiveInputStreamTest extends AbstractTest { @@ -184,4 +186,19 @@ void testSingleByteReadConsistentlyReturnsMinusOneAtEof() throws Exception { assertEquals(-1, archive.read()); } } + + @Test + @Issue("https://issues.apache.org/jira/browse/COMPRESS-711") + void testCrcVerification() throws Exception { + try (CpioArchiveInputStream archive = CpioArchiveInputStream.builder().setURI(getURI("bla.cpio")).get()) { + assertNotNull(archive.getNextEntry()); + assertDoesNotThrow(() -> { + final byte[] buffer = new byte[1024]; + // Read with an offset to test that the right bytes are checksummed + while (archive.read(buffer, 1, 1023) != -1) { + // noop + } + }); + } + } }
