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
+                }
+            });
+        }
+    }
 }

Reply via email to