COMPRESS-262 be more lenient when parsing tar headers as some dialect use up all space for big numbers

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/compress/trunk@1570452 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index ab06908..c8712e4 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -62,6 +62,11 @@
         metadata that can be provided via GzipParameters when writing
         a gzip stream.
       </action>
+      <action issue="COMPRESS-262" type="fix" date="2014-02-21">
+        TarArchiveInputStream will now read archives created by tar
+        implementations that encode big numbers by not adding a
+        trailing NUL.
+      </action>
     </release>
     <release version="1.7" date="2014-01-20"
              description="Release 1.7">
diff --git a/src/main/java/org/apache/commons/compress/archivers/tar/TarUtils.java b/src/main/java/org/apache/commons/compress/archivers/tar/TarUtils.java
index 1579dcb..4cf32d6 100644
--- a/src/main/java/org/apache/commons/compress/archivers/tar/TarUtils.java
+++ b/src/main/java/org/apache/commons/compress/archivers/tar/TarUtils.java
@@ -121,21 +121,19 @@
             }
         }
 
-        // Must have trailing NUL or space
-        byte trailer;
-        trailer = buffer[end-1];
-        if (trailer == 0 || trailer == ' '){
-            end--;
-        } else {
-            throw new IllegalArgumentException(
-                    exceptionMessage(buffer, offset, length, end-1, trailer));
-        }
-        // May have additional NULs or spaces
-        trailer = buffer[end - 1];
-        while (start < end - 1 && (trailer == 0 || trailer == ' ')) {
+        // Trim all trailing NULs and spaces.
+        // The ustar and POSIX tar specs require a trailing NUL or
+        // space but some implementations use the extra digit for big
+        // sizes/uids/gids ...
+        byte trailer = buffer[end - 1];
+        while (start < end && (trailer == 0 || trailer == ' ')) {
             end--;
             trailer = buffer[end - 1];
         }
+        if (start == end) {
+            throw new IllegalArgumentException(
+                    exceptionMessage(buffer, offset, length, start, trailer));
+        }
 
         for ( ;start < end; start++) {
             final byte currentByte = buffer[start];
diff --git a/src/test/java/org/apache/commons/compress/archivers/tar/TarUtilsTest.java b/src/test/java/org/apache/commons/compress/archivers/tar/TarUtilsTest.java
index f45491a..7d6eb77 100644
--- a/src/test/java/org/apache/commons/compress/archivers/tar/TarUtilsTest.java
+++ b/src/test/java/org/apache/commons/compress/archivers/tar/TarUtilsTest.java
@@ -47,9 +47,13 @@
         long value; 
         byte [] buffer;
         final long MAX_OCTAL  = 077777777777L; // Allowed 11 digits
-        final String maxOctal = "77777777777 "; // Maximum valid octal
+        final long MAX_OCTAL_OVERFLOW  = 0777777777777L; // in fact 12 for some implementations
+        final String maxOctal = "777777777777"; // Maximum valid octal
         buffer = maxOctal.getBytes(CharsetNames.UTF_8);
         value = TarUtils.parseOctal(buffer,0, buffer.length);
+        assertEquals(MAX_OCTAL_OVERFLOW, value);
+        buffer[buffer.length - 1] = ' ';
+        value = TarUtils.parseOctal(buffer,0, buffer.length);
         assertEquals(MAX_OCTAL, value);
         buffer[buffer.length-1]=0;
         value = TarUtils.parseOctal(buffer,0, buffer.length);
@@ -88,12 +92,6 @@
             fail("Expected IllegalArgumentException");
         } catch (IllegalArgumentException expected) {
         }
-        buffer = "77777777777".getBytes(CharsetNames.UTF_8); // Invalid input - no trailer
-        try {
-            TarUtils.parseOctal(buffer,0, buffer.length);
-            fail("Expected IllegalArgumentException - no trailer");
-        } catch (IllegalArgumentException expected) {
-        }
         buffer = " 0 07 ".getBytes(CharsetNames.UTF_8); // Invalid - embedded space
         try {
             TarUtils.parseOctal(buffer,0, buffer.length);