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

desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git


The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
     new 17167a7  Fix a bug in TIFF LZW compression when the code size is about 
to move to 13 bits (which is illegal) but is immediately followed by a 
`CLEAR_CODE` (which make it okay).
17167a7 is described below

commit 17167a7b18f6f9dc7ba0b1773182214af4ed1295
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Wed Feb 2 00:08:16 2022 +0100

    Fix a bug in TIFF LZW compression when the code size is about to move to 13 
bits (which is illegal) but is immediately followed by a `CLEAR_CODE` (which 
make it okay).
---
 .../apache/sis/internal/storage/inflater/LZW.java  | 34 +++++++++++++---------
 1 file changed, 21 insertions(+), 13 deletions(-)

diff --git 
a/storage/sis-geotiff/src/main/java/org/apache/sis/internal/storage/inflater/LZW.java
 
b/storage/sis-geotiff/src/main/java/org/apache/sis/internal/storage/inflater/LZW.java
index 583732f..cf7fe90 100644
--- 
a/storage/sis-geotiff/src/main/java/org/apache/sis/internal/storage/inflater/LZW.java
+++ 
b/storage/sis-geotiff/src/main/java/org/apache/sis/internal/storage/inflater/LZW.java
@@ -115,7 +115,7 @@ final class LZW extends CompressionChannel {
      */
     public LZW(final ChannelDataInput input) {
         super(input);
-        sequencesForCodes = new byte[(1 << MAX_CODE_SIZE) - 
FIRST_ADAPTATIVE_CODE][];
+        sequencesForCodes = new byte[(1 << MAX_CODE_SIZE) - 
OFFSET_TO_MAXIMUM][];
     }
 
     /**
@@ -151,19 +151,17 @@ final class LZW extends CompressionChannel {
          */
         if (pending != null) {
             final int r = target.remaining();
-            if (pending.length <= r) {
+            final int n = pending.length;
+            if (n <= r) {
                 target.put(pending);
                 pending = null;
-                if (done) return r;
+                if (done) return n;
             } else {
                 target.put(pending, 0, r);
-                pending = Arrays.copyOfRange(pending, r, pending.length);
+                pending = Arrays.copyOfRange(pending, r, n);
                 return r;   // Can not write more than what we just wrote.
             }
-        } else {
-            done |= finished();
-        }
-        if (done) {
+        } else if (done |= finished()) {
             return -1;
         }
         /*
@@ -228,11 +226,21 @@ final class LZW extends CompressionChannel {
                         throw unexpectedData();
                     }
                 }
-                sequencesForCodes[nextAvailableEntry] = addToTable;
+                try {
+                    sequencesForCodes[nextAvailableEntry] = addToTable;
+                } catch (ArrayIndexOutOfBoundsException e) {
+                    throw (IOException) unexpectedData().initCause(e);
+                }
                 if (++nextAvailableEntry == maximumIndex) {
-                    maximumIndex = (1 << ++codeSize) - OFFSET_TO_MAXIMUM;
-                    if (codeSize > MAX_CODE_SIZE) {
-                        throw new IOException();
+                    if (codeSize < MAX_CODE_SIZE) {
+                        maximumIndex = (1 << ++codeSize) - OFFSET_TO_MAXIMUM;
+                    } else {
+                        /*
+                         * Incrementing the size to 13 bits is an error 
because the TIFF specification
+                         * limits the size to 12 bits, but some files encode 
an EOI_CODE or CLEAR_CODE
+                         * immediately after this code. If this is not the 
case, we will have an index
+                         * out of bounds exception in the next iteration, 
which is caught above.
+                         */
                     }
                 }
                 /*
@@ -248,7 +256,7 @@ final class LZW extends CompressionChannel {
             }
         }
         previousSequence = write;
-        done = (code == EOI_CODE && pending != null);
+        done = (code == EOI_CODE);
         return target.position() - start;
     }
 

Reply via email to