takaaki nakama created COMPRESS-678: ---------------------------------------
Summary: ArArchiveInputStream.getNextArEntryu() cause IOException "Invalid entry trailer." Key: COMPRESS-678 URL: https://issues.apache.org/jira/browse/COMPRESS-678 Project: Commons Compress Issue Type: Bug Components: Archivers Affects Versions: 1.26.1 Reporter: takaaki nakama Using ArArchiveInputStream, reading content created by ArArchiveOutputStream causes IOException "Invalid entry trailer." at specific conditions. h4. Conditions 1. LongFILE_BSD mode is enabled 2. Ar file contains at least two entries. 1. First entry's name length is longer than 16bytes and odd 2. First entry's body length is odd. 3. Second entry's name length is odd h4. Cause ArArchiveOutputStream add padding if entryOffset is odd. This entryOffset only includes body length, but not entry name length. https://github.com/apache/commons-compress/blob/master/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStream.java#L80 ArArchiveIutputStream try to remove padding when offset is odd. This offset includes body length and name length. https://github.com/apache/commons-compress/blob/master/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java#L266 So encoding/decoding use different logics for adding, and at specific conditions, ArArchiveIutputStream remove 1byte that is actually not padding by mistake. h4. Reproduction Code {code:java} package test; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import org.apache.commons.compress.archivers.ar.ArArchiveEntry; import org.apache.commons.compress.archivers.ar.ArArchiveInputStream; import org.apache.commons.compress.archivers.ar.ArArchiveOutputStream; import org.junit.Test; public class ArTest { @Test public void test() throws IOException { File file = new File("test.ar"); ArArchiveOutputStream arOut = new ArArchiveOutputStream(new FileOutputStream(file)); arOut.setLongFileMode(ArArchiveOutputStream.LONGFILE_BSD); arOut.putArchiveEntry(new ArArchiveEntry("01234567891234567", 1)); arOut.write(new byte[]{1}); arOut.closeArchiveEntry(); arOut.putArchiveEntry(new ArArchiveEntry("a", 1)); arOut.write(new byte[]{1}); arOut.closeArchiveEntry(); arOut.close(); ArArchiveInputStream arIn = new ArArchiveInputStream(new FileInputStream(file)); ArArchiveEntry entry = arIn.getNextArEntry(); System.out.println(entry.getName()); arIn.readAllBytes(); entry = arIn.getNextArEntry(); System.out.println(entry.getName()); // <- This line causes the exception. } }{code} h4. Error stack Trace {code:java} java.io.IOException: Invalid entry trailer. not read the content? Occurred at byte: 146 at org.apache.commons.compress.archivers.ar.ArArchiveInputStream.getNextArEntry(ArArchiveInputStream.java:294) at org.apache.druid.mila.ArTest.test(ArTest.java:34) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) at java.base/java.lang.reflect.Method.invoke(Method.java:580) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306) at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63) at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329) at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293) at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306) at org.junit.runners.ParentRunner.run(ParentRunner.java:413) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:112) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:40) at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:60) at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:52) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) at java.base/java.lang.reflect.Method.invoke(Method.java:580) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33) at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94) at jdk.proxy1/jdk.proxy1.$Proxy2.processTestClass(Unknown Source) at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176) at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129) at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100) at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60) at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56) at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:113) at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:65) at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69) at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74) {code} -- This message was sent by Atlassian Jira (v8.20.10#820010)