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

bodewig 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 2887391  COMPRESS-575 harden parser for PAX 1.0 sparse struct blocks
2887391 is described below

commit 2887391296216e5196921f04bea8cd834843cfe2
Author: Stefan Bodewig <bode...@apache.org>
AuthorDate: Sat May 1 13:47:25 2021 +0200

    COMPRESS-575 harden parser for PAX 1.0 sparse struct blocks
---
 .../commons/compress/archivers/tar/TarUtils.java   |  19 +++-
 .../compress/archivers/tar/TarUtilsTest.java       | 119 +++++++++++++++++++++
 2 files changed, 136 insertions(+), 2 deletions(-)

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 eee894e..3ba7a1b 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
@@ -882,14 +882,26 @@ public class TarUtils {
 
         long[] readResult = readLineOfNumberForPax1X(inputStream);
         long sparseHeadersCount = readResult[0];
+        if (sparseHeadersCount < 0) {
+            // overflow while reading number?
+            throw new IOException("Corrupted TAR archive. Negative value in 
sparse headers block");
+        }
         bytesRead += readResult[1];
         while (sparseHeadersCount-- > 0) {
             readResult = readLineOfNumberForPax1X(inputStream);
-            long sparseOffset = readResult[0];
+            final long sparseOffset = readResult[0];
+            if (sparseOffset < 0) {
+                throw new IOException("Corrupted TAR archive."
+                    + " Sparse header block offset contains negative value");
+            }
             bytesRead += readResult[1];
 
             readResult = readLineOfNumberForPax1X(inputStream);
-            long sparseNumbytes = readResult[0];
+            final long sparseNumbytes = readResult[0];
+            if (sparseNumbytes < 0) {
+                throw new IOException("Corrupted TAR archive."
+                    + " Sparse header block numbytes contains negative value");
+            }
             bytesRead += readResult[1];
             sparseHeaders.add(new TarArchiveStructSparse(sparseOffset, 
sparseNumbytes));
         }
@@ -918,6 +930,9 @@ public class TarUtils {
             if (number == -1) {
                 throw new IOException("Unexpected EOF when reading parse 
information of 1.X PAX format");
             }
+            if (number < '0' || number > '9') {
+                throw new IOException("Corrupted TAR archive. Non-numeric 
value in sparse headers block");
+            }
             result = result * 10 + (number - '0');
         }
         bytesRead += 1;
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 0bca2f0..adb2408 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
@@ -672,4 +672,123 @@ public class TarUtilsTest {
         TarUtils.parsePAX01SparseHeaders(map);
     }
 
+    @Test
+    public void parsePAX1XSparseHeaders() throws Exception {
+        final byte[] header = ("1\n"
+                + "0\n"
+                + "20\n")
+            .getBytes();
+        final byte[] block = new byte[512];
+        System.arraycopy(header, 0, block, 0, header.length);
+        try (ByteArrayInputStream in = new ByteArrayInputStream(block)) {
+            final List<TarArchiveStructSparse> sparse = 
TarUtils.parsePAX1XSparseHeaders(in, 512);
+            assertEquals(1, sparse.size());
+            assertEquals(0, sparse.get(0).getOffset());
+            assertEquals(20, sparse.get(0).getNumbytes());
+            assertEquals(-1, in.read());
+        }
+    }
+
+    @Test
+    public void parsePAX1XSparseHeadersRejectsIncompleteLastLine() throws 
Exception {
+        thrown.expect(IOException.class);
+        thrown.expectMessage(startsWith("Unexpected EOF"));
+        final byte[] header = ("1\n"
+                + "0\n"
+                + "20")
+            .getBytes();
+        try (ByteArrayInputStream in = new ByteArrayInputStream(header)) {
+            TarUtils.parsePAX1XSparseHeaders(in, 512);
+        }
+    }
+
+    @Test
+    public void parsePAX1XSparseHeadersRejectsNonNumericNumberOfEntries() 
throws Exception {
+        thrown.expect(IOException.class);
+        thrown.expectMessage(startsWith("Corrupted TAR archive."));
+        final byte[] header = ("x\n"
+                + "0\n"
+                + "20\n")
+            .getBytes();
+        final byte[] block = new byte[512];
+        System.arraycopy(header, 0, block, 0, header.length);
+        try (ByteArrayInputStream in = new ByteArrayInputStream(block)) {
+            TarUtils.parsePAX1XSparseHeaders(in, 512);
+        }
+    }
+
+    @Test
+    public void parsePAX1XSparseHeadersRejectsNonNumericOffset() throws 
Exception {
+        thrown.expect(IOException.class);
+        thrown.expectMessage(startsWith("Corrupted TAR archive."));
+        final byte[] header = ("1\n"
+                + "x\n"
+                + "20\n")
+            .getBytes();
+        final byte[] block = new byte[512];
+        System.arraycopy(header, 0, block, 0, header.length);
+        try (ByteArrayInputStream in = new ByteArrayInputStream(block)) {
+            TarUtils.parsePAX1XSparseHeaders(in, 512);
+        }
+    }
+
+    @Test
+    public void parsePAX1XSparseHeadersRejectsNonNumericNumbytes() throws 
Exception {
+        thrown.expect(IOException.class);
+        thrown.expectMessage(startsWith("Corrupted TAR archive."));
+        final byte[] header = ("1\n"
+                + "0\n"
+                + "2x\n")
+            .getBytes();
+        final byte[] block = new byte[512];
+        System.arraycopy(header, 0, block, 0, header.length);
+        try (ByteArrayInputStream in = new ByteArrayInputStream(block)) {
+            TarUtils.parsePAX1XSparseHeaders(in, 512);
+        }
+    }
+    @Test
+    public void parsePAX1XSparseHeadersRejectsNegativeNumberOfEntries() throws 
Exception {
+        thrown.expect(IOException.class);
+        thrown.expectMessage(startsWith("Corrupted TAR archive."));
+        final byte[] header = 
("111111111111111111111111111111111111111111111111111111111111111\n"
+                + "0\n"
+                + "20\n")
+            .getBytes();
+        final byte[] block = new byte[512];
+        System.arraycopy(header, 0, block, 0, header.length);
+        try (ByteArrayInputStream in = new ByteArrayInputStream(block)) {
+            TarUtils.parsePAX1XSparseHeaders(in, 512);
+        }
+    }
+
+    @Test
+    public void parsePAX1XSparseHeadersRejectsNegativeOffset() throws 
Exception {
+        thrown.expect(IOException.class);
+        thrown.expectMessage(startsWith("Corrupted TAR archive."));
+        final byte[] header = ("1\n"
+                + 
"111111111111111111111111111111111111111111111111111111111111111\n"
+                + "20\n")
+            .getBytes();
+        final byte[] block = new byte[512];
+        System.arraycopy(header, 0, block, 0, header.length);
+        try (ByteArrayInputStream in = new ByteArrayInputStream(block)) {
+            TarUtils.parsePAX1XSparseHeaders(in, 512);
+        }
+    }
+
+    @Test
+    public void parsePAX1XSparseHeadersRejectsNegativeNumbytes() throws 
Exception {
+        thrown.expect(IOException.class);
+        thrown.expectMessage(startsWith("Corrupted TAR archive."));
+        final byte[] header = ("1\n"
+                + "0\n"
+                + 
"111111111111111111111111111111111111111111111111111111111111111\n")
+            .getBytes();
+        final byte[] block = new byte[512];
+        System.arraycopy(header, 0, block, 0, header.length);
+        try (ByteArrayInputStream in = new ByteArrayInputStream(block)) {
+            TarUtils.parsePAX1XSparseHeaders(in, 512);
+        }
+    }
+
 }

Reply via email to