This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git


The following commit(s) were added to refs/heads/master by this push:
     new 0c67cb8e5 [COMPRESS-700] Can't detect file 
flutter_awesome_buttons-0.1.0.tar as a TAR file
0c67cb8e5 is described below

commit 0c67cb8e5a1221acbd427395036d408b53dc9f99
Author: Gary Gregory <garydgreg...@gmail.com>
AuthorDate: Mon Jun 2 08:47:40 2025 -0400

    [COMPRESS-700] Can't detect file flutter_awesome_buttons-0.1.0.tar as a
    TAR file
---
 src/changes/changes.xml                            |   3 +-
 .../compress/archivers/ArchiveStreamFactory.java   |   9 ++-
 .../commons/compress/DetectArchiverTest.java       |  73 +++++++++++++++++++--
 .../compress/archivers/tar/Compress700Test.java    |  10 ++-
 ...-fail.tar => flutter_awesome_buttons-0.1.0.tar} | Bin
 5 files changed, 80 insertions(+), 15 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 27b152a5c..b06034e5e 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -96,7 +96,8 @@ The <action> type attribute can be add,update,fix,remove.
       <action type="fix" dev="ggregory" due-to="Gary 
Gregory">ArArchiveInputStream.getBSDLongName(String) now throws its 
EOFException with a message.</action>
       <action type="fix" dev="ggregory" due-to="Gary 
Gregory">ZipEncodingHelper.getZipEncoding(*) can throw NullPointerException and 
IllegalArgumentException on bad input instead of returning a value using the 
default Charset.</action>
       <action type="fix" dev="ggregory" due-to="Gary Gregory">Javadoc 
improvements throughout.</action>
-      <action type="fix" dev="ggregory" due-to="Gary Gregory" issue= 
"COMPRESS-699">ArchiveStreamFactory.detect(inputStream) ArchiveException for 
TAR regression.</action>
+      <action type="fix" dev="ggregory" due-to="Gary Gregory" 
issue="COMPRESS-699">ArchiveStreamFactory.detect(inputStream) ArchiveException 
for TAR regression.</action>
+      <action type="fix" dev="ggregory" due-to="Gary Gregory" 
issue="COMPRESS-700">Can't detect file flutter_awesome_buttons-0.1.0.tar as a 
TAR file.</action>
       <!-- ADD -->
       <action type="add" dev="ggregory" due-to="Gary Gregory">Add 
GzipParameters.getModificationInstant().</action>
       <action type="add" dev="ggregory" due-to="Gary Gregory">Add 
GzipParameters.setModificationInstant(Instant).</action>
diff --git 
a/src/main/java/org/apache/commons/compress/archivers/ArchiveStreamFactory.java 
b/src/main/java/org/apache/commons/compress/archivers/ArchiveStreamFactory.java
index 4e066e4e7..88eb793a7 100644
--- 
a/src/main/java/org/apache/commons/compress/archivers/ArchiveStreamFactory.java
+++ 
b/src/main/java/org/apache/commons/compress/archivers/ArchiveStreamFactory.java
@@ -272,14 +272,14 @@ public static String detect(final InputStream in) throws 
ArchiveException {
         if (signatureLength >= TAR_HEADER_SIZE) {
             try (TarArchiveInputStream inputStream = new 
TarArchiveInputStream(new ByteArrayInputStream(tarHeader))) {
                 // COMPRESS-191 - verify the header checksum
-                // COMPRESS-644 - do not allow zero byte file entries
                 TarArchiveEntry entry = inputStream.getNextEntry();
                 // try to find the first non-directory entry within the first 
10 entries.
                 int count = 0;
                 while (entry != null && entry.isDirectory() && 
entry.isCheckSumOK() && count++ < TAR_TEST_ENTRY_COUNT) {
                     entry = inputStream.getNextEntry();
                 }
-                if (entry != null && entry.isCheckSumOK() && 
!entry.isDirectory() && entry.getSize() > 0 || count > 0) {
+                if (entry != null && entry.isCheckSumOK() && 
!entry.isDirectory() && isName(entry.getGroupName()) && isName(entry.getName())
+                        && isName(entry.getUserName()) || count > 0) {
                     return TAR;
                 }
             } catch (final Exception ignored) {
@@ -347,6 +347,11 @@ public static SortedMap<String, ArchiveStreamProvider> 
findAvailableArchiveOutpu
         });
     }
 
+    private static boolean isName(final String value) {
+        // Expect ASCII https://www.mkssoftware.com/docs/man4/tar.4.asp
+        return value.isEmpty() || value.chars().allMatch(ch -> ch > 31 && ch < 
128);
+    }
+
     static void putAll(final Set<String> names, final ArchiveStreamProvider 
provider, final TreeMap<String, ArchiveStreamProvider> map) {
         names.forEach(name -> map.put(toKey(name), provider));
     }
diff --git a/src/test/java/org/apache/commons/compress/DetectArchiverTest.java 
b/src/test/java/org/apache/commons/compress/DetectArchiverTest.java
index f6c96a000..aafd12d3c 100644
--- a/src/test/java/org/apache/commons/compress/DetectArchiverTest.java
+++ b/src/test/java/org/apache/commons/compress/DetectArchiverTest.java
@@ -18,18 +18,23 @@
  */
 package org.apache.commons.compress;
 
-import static org.junit.Assert.assertNull;
 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.io.BufferedInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.nio.file.attribute.FileTime;
+import java.time.Instant;
+import java.util.Collections;
 
 import org.apache.commons.compress.archivers.ArchiveEntry;
 import org.apache.commons.compress.archivers.ArchiveException;
@@ -38,6 +43,7 @@
 import org.apache.commons.compress.archivers.ar.ArArchiveInputStream;
 import org.apache.commons.compress.archivers.arj.ArjArchiveInputStream;
 import org.apache.commons.compress.archivers.cpio.CpioArchiveInputStream;
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
 import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
 import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
 import org.junit.jupiter.api.Test;
@@ -75,6 +81,10 @@ private BufferedInputStream createBufferedInputStream(final 
String resource) thr
         return new BufferedInputStream(newInputStream(resource));
     }
 
+    private boolean isValidName(final String value) {
+       return value.isEmpty() || value.chars().allMatch(ch -> ch > 31 && ch < 
128);
+    }
+
     @Test
     public void testCOMPRESS_117() throws Exception {
         try (ArchiveInputStream<?> tar = 
createArchiveInputStream("COMPRESS-117.tar")) {
@@ -131,11 +141,6 @@ public void testDetection() throws Exception {
 
     }
 
-    @Test
-    public void testDetectionNotArchive() {
-        assertThrows(ArchiveException.class, () -> 
createArchiveInputStream("test.txt"));
-    }
-
     // Check that the empty archives created by the code are readable
 
     // Not possible to detect empty "ar" archive as it is completely empty
@@ -143,6 +148,11 @@ public void testDetectionNotArchive() {
 //        emptyArchive("ar");
 //    }
 
+    @Test
+    public void testDetectionNotArchive() {
+        assertThrows(ArchiveException.class, () -> 
createArchiveInputStream("test.txt"));
+    }
+
     @Test
     public void testDetectOldTarFormatArchive() throws Exception {
         try (ArchiveInputStream<?> tar = 
createArchiveInputStream("COMPRESS-612/test-times-star-folder.tar")) {
@@ -184,4 +194,55 @@ public void testIcoFile() {
             }
         });
     }
+
+    @Test
+    public void testIcoFileFirstTarArchiveEntry() throws Exception {
+        try (TarArchiveInputStream inputStream = new 
TarArchiveInputStream(createBufferedInputStream("org/apache/commons/compress/COMPRESS-644/ARW05UP.ICO")))
 {
+            final TarArchiveEntry entry = inputStream.getNextEntry();
+            // Find hints that the file is not a TAR file.
+            assertNull(entry.getCreationTime());
+            assertEquals(-1, entry.getDataOffset());
+            assertEquals(0, entry.getDevMajor());
+            assertEquals(0, entry.getDevMinor());
+            assertEquals(Collections.emptyMap(), entry.getExtraPaxHeaders());
+            assertEquals(0, entry.getGroupId());
+            assertFalse(isValidName(entry.getGroupName()), 
entry::getGroupName); // hint
+            assertNull(entry.getLastAccessTime());
+            assertEquals(0, entry.getLastModifiedDate().getTime());  // hint
+            assertEquals(FileTime.from(Instant.EPOCH), 
entry.getLastModifiedTime()); // hint
+            assertEquals(0, entry.getLinkFlag()); // NUL (not really a hint)
+            assertEquals("", entry.getLinkName());
+            assertEquals(0, entry.getLongGroupId());
+            assertEquals(16777215, entry.getLongUserId()); // hint?
+            assertEquals(0, entry.getMode()); // hint?
+            assertEquals(0, entry.getModTime().getTime()); // hint?
+            assertFalse(isValidName(entry.getName()), entry::getName); // hint
+            assertNull(entry.getPath());
+            assertEquals(0, entry.getRealSize());
+            assertEquals(0, entry.getSize());
+            assertNull(entry.getStatusChangeTime());
+            assertEquals(16777215, entry.getUserId()); // hint?
+            assertFalse(isValidName(entry.getUserName()), entry::getUserName); 
// hint
+            assertTrue(entry.isFile());
+            assertFalse(entry.isBlockDevice());
+            assertFalse(entry.isCharacterDevice());
+            assertTrue(entry.isCheckSumOK());
+            assertFalse(entry.isDirectory());
+            assertFalse(entry.isExtended());
+            assertFalse(entry.isFIFO());
+            assertFalse(entry.isGlobalPaxHeader());
+            assertFalse(entry.isGNULongLinkEntry());
+            assertFalse(entry.isGNULongNameEntry());
+            assertFalse(entry.isGNUSparse());
+            assertFalse(entry.isLink());
+            assertFalse(entry.isOldGNUSparse());
+            assertFalse(entry.isPaxGNU1XSparse());
+            assertFalse(entry.isPaxGNUSparse());
+            assertFalse(entry.isPaxHeader());
+            assertFalse(entry.isSparse());
+            assertFalse(entry.isStarSparse());
+            assertTrue(entry.isStreamContiguous());
+            assertFalse(entry.isSymbolicLink());
+        }
+    }
 }
diff --git 
a/src/test/java/org/apache/commons/compress/archivers/tar/Compress700Test.java 
b/src/test/java/org/apache/commons/compress/archivers/tar/Compress700Test.java
index edf561b8c..aa03d2722 100644
--- 
a/src/test/java/org/apache/commons/compress/archivers/tar/Compress700Test.java
+++ 
b/src/test/java/org/apache/commons/compress/archivers/tar/Compress700Test.java
@@ -38,16 +38,14 @@
 import java.util.List;
 
 import org.apache.commons.compress.archivers.ArchiveStreamFactory;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
 
 /**
  * Tests https://issues.apache.org/jira/browse/COMPRESS-699
  */
 public class Compress700Test {
 
-    private static final Path PATH = 
Paths.get("src/test/resources/org/apache/commons/compress/COMPRESS-700/flutter_awesome_buttons-0.1.0-fail.tar");
+    private static final Path PATH = 
Paths.get("src/test/resources/org/apache/commons/compress/COMPRESS-700/flutter_awesome_buttons-0.1.0.tar");
 
     @Test
     public void testFirstTarArchiveEntry() throws Exception {
@@ -187,8 +185,8 @@ public void testListEntries() throws IOException {
         }
     }
 
-    @Disabled
-    @Ignore
+    //@Disabled
+    //@Ignore
     @Test
     public void testTarArchive() throws Exception {
         try (BufferedInputStream fileInputStream = new 
BufferedInputStream(Files.newInputStream(PATH))) {
diff --git 
a/src/test/resources/org/apache/commons/compress/COMPRESS-700/flutter_awesome_buttons-0.1.0-fail.tar
 
b/src/test/resources/org/apache/commons/compress/COMPRESS-700/flutter_awesome_buttons-0.1.0.tar
similarity index 100%
rename from 
src/test/resources/org/apache/commons/compress/COMPRESS-700/flutter_awesome_buttons-0.1.0-fail.tar
rename to 
src/test/resources/org/apache/commons/compress/COMPRESS-700/flutter_awesome_buttons-0.1.0.tar

Reply via email to