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)

Reply via email to