AWARE SYSTEMS
TIFF and LibTiff Mail List Archive

1994.10.13 18:44 "Kudos + possible bug in 3.3 PackBits", by HostFax

Hello all,

First off, thanks to the many people who gave me advice on compiling libtiff 3.3 under gcc. You were right -- the problem was my 2.2 version of gcc. The 2.5.8 version works wonderfully, though I would not recommend 2.6.0, at least for ISC (I got assembler errors when compiling with it).

Incase nobody has mentioned this yet, there may be a bug in libtiff/tif_packbits.c. It looks like line 226 (cc -= n;) should not be there. Here's the $Header for the version I have:

/* $Header: /usr/people/sam/tiff/libtiff/RCS/tif_packbits.c,v 1.39 1994/07/27 01:59:44 sam Exp $ */

I compared this file to an old 3.0 version and found that line 226 and the extra cc-- on line 213 were the only changes that might have caused the errors I was getting (PackBitsDecode: Not enough data for scanline n).

When I commented out line 226, everything suddenly started working again. I tend to think line 213 is a bug fix for 3.0, since it makes sense that you want to decrement the input byte count on every byte read from the buffer. Such a bug in 3.0 would not have affected anything so long as the scanlines actually encoded the right amount of data. This would explain why my 3.0 libtiff works just as well as my (modified) 3.3.

The following is my modified copy of PackBitsDecode():

( Sam: Sorry, I would have given a diff, but I understand you've already moved on to a new beta version. )

Regards,
-Mike Stanfill

-----valuable-coupon-----clip'n'save-----valuable-coupon-----clip'n'save-----

static int
PackBitsDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
{
        char *bp;
        tsize_t cc;

        bp = (char*) tif->tif_rawcp;
        cc = tif->tif_rawcc;
        while (cc > 0 && (long)occ > 0) {
                long n;
                int b;
                
                n = (long) *bp++, cc--;
                /*
                 * Watch out for compilers that
                 * don't sign extend chars...
                 */
                if (n >= 128)
                        n -= 256;
                if (n < 0) {            /* replicate next byte -n+1 times */
                        cc--;
                        if (n == -128)  /* nop */
                                continue;
                        n = -n + 1;
                        occ -= n;
/*  bug? ----->         cc -= n;        */
                        for (b = *bp++; n-- > 0;)
                                *op++ = b;
                } else {                /* copy next n+1 bytes literally */
                        memcpy(op, bp, ++n);
                        op += n; occ -= n;
                        bp += n; cc -= n;
                }
        }
        tif->tif_rawcp = (tidata_t) bp;
        tif->tif_rawcc = cc;
        if (occ > 0) {
                TIFFError(tif->tif_name,
                    "PackBitsDecode: Not enough data for scanline %ld",
                    (long) tif->tif_row);
                return (0);
        }
        /* check for buffer overruns? */
        return (1);
}