[
https://issues.apache.org/jira/browse/COMPRESS-678?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
takaaki nakama updated COMPRESS-678:
------------------------------------
Description:
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 padding, 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(); // <- This line causes the exception.
System.out.println(entry.getName());
}
}{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}
was:
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 padding, 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}
> ArArchiveInputStream.getNextArEntry() 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
> Priority: Minor
>
> 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 padding, 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(); // <- This line causes the exception.
> System.out.println(entry.getName());
> }
> }{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)