2015.05.08 17:51 "[Tiff] Long standing bug in LibTIFF LZW compression", by Andy Cave

2015.06.11 16:15 "Re: [Tiff] Long standing bug in LibTIFF LZW compression", by Lee Howard

Attached is the untested patch. (I'm merely following Andy's instructions in creating a patch for him.)

On 05/08/2015 10:51 AM, Andy Cave wrote:

Dear All,

There is a longstanding bug in the LZW decompressor in LibTIFF. It fails to decode files that contain two consecutive CODE_CLEAR codes. These are allowed by the LZW spec and the same data sequence is correctly decoded by Acrobat if you wrap the data in a PDF file.

The fix is simple:

  1. Add "do {" after the line "if (code == CODE_CLEAR) {" in both LZWDecode and LZWDecodeCompat.
  2. Add "} while (code == CODE_CLEAR);" before the line " if (code == CODE_EOI)" (half a dozen lines or so down from the first change) in both LZWDecode and LZWDecodeCompat.
  3. I have no idea how to submit a diff of the fix or fix the public domain source, so if someone could help who knows how to, it should do no harm to fix the bug.

--- libtiff/tif_lzw.c.orig      2015-06-11 09:09:07.333492975 -0700

+++ libtiff/tif_lzw.c   2015-06-11 09:13:16.110060482 -0700

@@ -436,13 +436,15 @@
                if (code == CODE_EOI)
                        break;
                if (code == CODE_CLEAR) {

-                       nbits = BITS_MIN;
-                       nbitsmask = MAXCODE(BITS_MIN);
-                       maxcodep = sp->dec_codetab + nbitsmask-1;
-                       NextCode(tif, sp, bp, code, GetNextCode);
+                       do {
+                               free_entp = sp->dec_codetab + CODE_FIRST;
+                               _TIFFmemset(free_entp, 0,
+                                           (CSIZE - CODE_FIRST) * sizeof (code_t));
+                               nbits = BITS_MIN;
+                               nbitsmask = MAXCODE(BITS_MIN);
+                               maxcodep = sp->dec_codetab + nbitsmask-1;
+                               NextCode(tif, sp, bp, code, GetNextCode);
+                       } while (code == CODE_CLEAR);   /* consecutive CODE_CLEAR codes */
                        if (code == CODE_EOI)
                                break;
                        if (code >= CODE_CLEAR) {
@@ -655,13 +657,15 @@
                if (code == CODE_EOI)
                        break;
                if (code == CODE_CLEAR) {
-                       free_entp = sp->dec_codetab + CODE_FIRST;
-                       _TIFFmemset(free_entp, 0,
-                                   (CSIZE - CODE_FIRST) * sizeof (code_t));
-                       nbits = BITS_MIN;
-                       nbitsmask = MAXCODE(BITS_MIN);
-                       maxcodep = sp->dec_codetab + nbitsmask;
-                       NextCode(tif, sp, bp, code, GetNextCodeCompat);
+                       do {
+                               free_entp = sp->dec_codetab + CODE_FIRST;
+                               _TIFFmemset(free_entp, 0,
+                                           (CSIZE - CODE_FIRST) * sizeof (code_t));
+                               nbits = BITS_MIN;
+                               nbitsmask = MAXCODE(BITS_MIN);
+                               maxcodep = sp->dec_codetab + nbitsmask;
+                               NextCode(tif, sp, bp, code, GetNextCodeCompat);
+                       } while (code == CODE_CLEAR);   /* consecutive CODE_CLEAR codes */

                        if (code == CODE_EOI)
                                break;
                        if (code >= CODE_CLEAR) {