]> git.saurik.com Git - wxWidgets.git/blobdiff - src/tiff/libtiff/tif_fax3.c
Reflect changes in stc.cpp in stc.cpp.in from which it's generated.
[wxWidgets.git] / src / tiff / libtiff / tif_fax3.c
index ed05633296d9e509a9c8b5b8d35ab6974c12f6d7..0ff36120a322bb4fd7fb74c564462d698ecd4776 100644 (file)
@@ -1,4 +1,3 @@
-/* $Id$ */
 
 /*
  * Copyright (c) 1990-1997 Sam Leffler
 
 /*
  * Copyright (c) 1990-1997 Sam Leffler
  * derived from this ``base state'' block.
  */
 typedef struct {
  * derived from this ``base state'' block.
  */
 typedef struct {
-        int     rw_mode;                /* O_RDONLY for decode, else encode */
-       int     mode;                   /* operating mode */
-       uint32  rowbytes;               /* bytes in a decoded scanline */
-       uint32  rowpixels;              /* pixels in a scanline */
-
-       uint16  cleanfaxdata;           /* CleanFaxData tag */
-       uint32  badfaxrun;              /* BadFaxRun tag */
-       uint32  badfaxlines;            /* BadFaxLines tag */
-       uint32  groupoptions;           /* Group 3/4 options tag */
-       uint32  recvparams;             /* encoded Class 2 session params */
-       char*   subaddress;             /* subaddress string */
-       uint32  recvtime;               /* time spent receiving (secs) */
-       char*   faxdcs;                 /* Table 2/T.30 encoded session params */
-       TIFFVGetMethod vgetparent;      /* super-class method */
-       TIFFVSetMethod vsetparent;      /* super-class method */
+       int      rw_mode;                /* O_RDONLY for decode, else encode */
+       int      mode;                   /* operating mode */
+       tmsize_t rowbytes;               /* bytes in a decoded scanline */
+       uint32   rowpixels;              /* pixels in a scanline */
+
+       uint16   cleanfaxdata;           /* CleanFaxData tag */
+       uint32   badfaxrun;              /* BadFaxRun tag */
+       uint32   badfaxlines;            /* BadFaxLines tag */
+       uint32   groupoptions;           /* Group 3/4 options tag */
+
+       TIFFVGetMethod  vgetparent;      /* super-class method */
+       TIFFVSetMethod  vsetparent;      /* super-class method */
+       TIFFPrintMethod printdir;        /* super-class method */
 } Fax3BaseState;
 #define        Fax3State(tif)          ((Fax3BaseState*) (tif)->tif_data)
 
 } Fax3BaseState;
 #define        Fax3State(tif)          ((Fax3BaseState*) (tif)->tif_data)
 
@@ -85,13 +82,14 @@ typedef struct {
        unsigned char*  refline;        /* reference line for 2d decoding */
        int     k;                      /* #rows left that can be 2d encoded */
        int     maxk;                   /* max #rows that can be 2d encoded */
        unsigned char*  refline;        /* reference line for 2d decoding */
        int     k;                      /* #rows left that can be 2d encoded */
        int     maxk;                   /* max #rows that can be 2d encoded */
+
+       int line;
 } Fax3CodecState;
 } Fax3CodecState;
-#define        DecoderState(tif)       ((Fax3CodecState*) Fax3State(tif))
-#define        EncoderState(tif)       ((Fax3CodecState*) Fax3State(tif))
+#define DecoderState(tif) ((Fax3CodecState*) Fax3State(tif))
+#define EncoderState(tif) ((Fax3CodecState*) Fax3State(tif))
 
 
-#define        is2DEncoding(sp) \
-       (sp->b.groupoptions & GROUP3OPT_2DENCODING)
-#define        isAligned(p,t)  ((((unsigned long)(p)) & (sizeof (t)-1)) == 0)
+#define is2DEncoding(sp) (sp->b.groupoptions & GROUP3OPT_2DENCODING)
+#define isAligned(p,t) ((((size_t)(p)) & (sizeof (t)-1)) == 0)
 
 /*
  * Group 3 and Group 4 Decoding.
 
 /*
  * Group 3 and Group 4 Decoding.
@@ -137,15 +135,15 @@ typedef struct {
     sp->bit = BitsAvail;                                               \
     sp->data = BitAcc;                                                 \
     sp->EOLcnt = EOLcnt;                                               \
     sp->bit = BitsAvail;                                               \
     sp->data = BitAcc;                                                 \
     sp->EOLcnt = EOLcnt;                                               \
-    tif->tif_rawcc -= (tidata_t) cp - tif->tif_rawcp;                  \
-    tif->tif_rawcp = (tidata_t) cp;                                    \
+    tif->tif_rawcc -= (tmsize_t)((uint8*) cp - tif->tif_rawcp);                \
+    tif->tif_rawcp = (uint8*) cp;                                      \
 } while (0)
 
 /*
  * Setup state for decoding a strip.
  */
 static int
 } while (0)
 
 /*
  * Setup state for decoding a strip.
  */
 static int
-Fax3PreDecode(TIFF* tif, tsample_t s)
+Fax3PreDecode(TIFF* tif, uint16 s)
 {
        Fax3CodecState* sp = DecoderState(tif);
 
 {
        Fax3CodecState* sp = DecoderState(tif);
 
@@ -167,6 +165,7 @@ Fax3PreDecode(TIFF* tif, tsample_t s)
                sp->refruns[0] = (uint32) sp->b.rowpixels;
                sp->refruns[1] = 0;
        }
                sp->refruns[0] = (uint32) sp->b.rowpixels;
                sp->refruns[1] = 0;
        }
+       sp->line = 0;
        return (1);
 }
 
        return (1);
 }
 
@@ -179,46 +178,44 @@ Fax3PreDecode(TIFF* tif, tsample_t s)
 static void
 Fax3Unexpected(const char* module, TIFF* tif, uint32 line, uint32 a0)
 {
 static void
 Fax3Unexpected(const char* module, TIFF* tif, uint32 line, uint32 a0)
 {
-       TIFFErrorExt(tif->tif_clientdata, module, "%s: Bad code word at line %lu of %s %lu (x %lu)",
-               tif->tif_name, (unsigned long) line, isTiled(tif) ? "tile" : "strip",
-          (unsigned long) (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip),
-          (unsigned long) a0);
+       TIFFErrorExt(tif->tif_clientdata, module, "Bad code word at line %u of %s %u (x %u)",
+           line, isTiled(tif) ? "tile" : "strip",
+           (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip),
+           a0);
 }
 }
-#define        unexpected(table, a0)   Fax3Unexpected(module, tif, line, a0)
+#define        unexpected(table, a0)   Fax3Unexpected(module, tif, sp->line, a0)
 
 static void
 Fax3Extension(const char* module, TIFF* tif, uint32 line, uint32 a0)
 {
        TIFFErrorExt(tif->tif_clientdata, module,
 
 static void
 Fax3Extension(const char* module, TIFF* tif, uint32 line, uint32 a0)
 {
        TIFFErrorExt(tif->tif_clientdata, module,
-           "%s: Uncompressed data (not supported) at line %lu of %s %lu (x %lu)",
-           tif->tif_name, (unsigned long) line, isTiled(tif) ? "tile" : "strip",
-       (unsigned long) (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip),
-       (unsigned long) a0);
+           "Uncompressed data (not supported) at line %u of %s %u (x %u)",
+           line, isTiled(tif) ? "tile" : "strip",
+           (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip),
+           a0);
 }
 }
-#define        extension(a0)   Fax3Extension(module, tif, line, a0)
+#define        extension(a0)   Fax3Extension(module, tif, sp->line, a0)
 
 static void
 Fax3BadLength(const char* module, TIFF* tif, uint32 line, uint32 a0, uint32 lastx)
 {
 
 static void
 Fax3BadLength(const char* module, TIFF* tif, uint32 line, uint32 a0, uint32 lastx)
 {
-       TIFFWarningExt(tif->tif_clientdata, module, "%s: %s at line %lu of %s %lu (got %lu, expected %lu)",
-           tif->tif_name,
+       TIFFWarningExt(tif->tif_clientdata, module, "%s at line %u of %s %u (got %u, expected %u)",
            a0 < lastx ? "Premature EOL" : "Line length mismatch",
            a0 < lastx ? "Premature EOL" : "Line length mismatch",
-           (unsigned long) line, isTiled(tif) ? "tile" : "strip",
-        (unsigned long) (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip),
-        (unsigned long) a0, lastx);
+           line, isTiled(tif) ? "tile" : "strip",
+           (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip),
+           a0, lastx);
 }
 }
-#define        badlength(a0,lastx)     Fax3BadLength(module, tif, line, a0, lastx)
+#define        badlength(a0,lastx)     Fax3BadLength(module, tif, sp->line, a0, lastx)
 
 static void
 Fax3PrematureEOF(const char* module, TIFF* tif, uint32 line, uint32 a0)
 {
 
 static void
 Fax3PrematureEOF(const char* module, TIFF* tif, uint32 line, uint32 a0)
 {
-       TIFFWarningExt(tif->tif_clientdata, module, "%s: Premature EOF at line %lu of %s %lu (x %lu)",
-           tif->tif_name,
-           (unsigned long) line, isTiled(tif) ? "tile" : "strip",
-        (unsigned long) (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip),
-        (unsigned long) a0);
+       TIFFWarningExt(tif->tif_clientdata, module, "Premature EOF at line %u of %s %u (x %u)",
+           line, isTiled(tif) ? "tile" : "strip",
+           (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip),
+           a0);
 }
 }
-#define        prematureEOF(a0)        Fax3PrematureEOF(module, tif, line, a0)
+#define        prematureEOF(a0)        Fax3PrematureEOF(module, tif, sp->line, a0)
 
 #define        Nop
 
 
 #define        Nop
 
@@ -226,15 +223,18 @@ Fax3PrematureEOF(const char* module, TIFF* tif, uint32 line, uint32 a0)
  * Decode the requested amount of G3 1D-encoded data.
  */
 static int
  * Decode the requested amount of G3 1D-encoded data.
  */
 static int
-Fax3Decode1D(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s)
+Fax3Decode1D(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s)
 {
        DECLARE_STATE(tif, sp, "Fax3Decode1D");
 {
        DECLARE_STATE(tif, sp, "Fax3Decode1D");
-        int line = 0;
-
        (void) s;
        (void) s;
+       if (occ % sp->b.rowbytes)
+       {
+               TIFFErrorExt(tif->tif_clientdata, module, "Fractional scanlines cannot be read");
+               return (-1);
+       }
        CACHE_STATE(tif, sp);
        thisrun = sp->curruns;
        CACHE_STATE(tif, sp);
        thisrun = sp->curruns;
-       while ((long)occ > 0) {
+       while (occ > 0) {
                a0 = 0;
                RunLength = 0;
                pa = thisrun;
                a0 = 0;
                RunLength = 0;
                pa = thisrun;
@@ -248,7 +248,7 @@ Fax3Decode1D(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s)
                (*sp->fill)(buf, thisrun, pa, lastx);
                buf += sp->b.rowbytes;
                occ -= sp->b.rowbytes;
                (*sp->fill)(buf, thisrun, pa, lastx);
                buf += sp->b.rowbytes;
                occ -= sp->b.rowbytes;
-                line++;
+               sp->line++;
                continue;
        EOF1D:                          /* premature EOF */
                CLEANUP_RUNS();
                continue;
        EOF1D:                          /* premature EOF */
                CLEANUP_RUNS();
@@ -266,15 +266,18 @@ Fax3Decode1D(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s)
  * Decode the requested amount of G3 2D-encoded data.
  */
 static int
  * Decode the requested amount of G3 2D-encoded data.
  */
 static int
-Fax3Decode2D(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s)
+Fax3Decode2D(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s)
 {
        DECLARE_STATE_2D(tif, sp, "Fax3Decode2D");
 {
        DECLARE_STATE_2D(tif, sp, "Fax3Decode2D");
-        int line = 0;
        int is1D;                       /* current line is 1d/2d-encoded */
        int is1D;                       /* current line is 1d/2d-encoded */
-
        (void) s;
        (void) s;
+       if (occ % sp->b.rowbytes)
+       {
+               TIFFErrorExt(tif->tif_clientdata, module, "Fractional scanlines cannot be read");
+               return (-1);
+       }
        CACHE_STATE(tif, sp);
        CACHE_STATE(tif, sp);
-       while ((long)occ > 0) {
+       while (occ > 0) {
                a0 = 0;
                RunLength = 0;
                pa = thisrun = sp->curruns;
                a0 = 0;
                RunLength = 0;
                pa = thisrun = sp->curruns;
@@ -302,7 +305,7 @@ Fax3Decode2D(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s)
                SWAP(uint32*, sp->curruns, sp->refruns);
                buf += sp->b.rowbytes;
                occ -= sp->b.rowbytes;
                SWAP(uint32*, sp->curruns, sp->refruns);
                buf += sp->b.rowbytes;
                occ -= sp->b.rowbytes;
-                line++;
+               sp->line++;
                continue;
        EOF2D:                          /* premature EOF */
                CLEANUP_RUNS();
                continue;
        EOF2D:                          /* premature EOF */
                CLEANUP_RUNS();
@@ -322,7 +325,7 @@ Fax3Decode2D(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s)
  * this is <8 bytes.  We optimize the code here to reflect the
  * machine characteristics.
  */
  * this is <8 bytes.  We optimize the code here to reflect the
  * machine characteristics.
  */
-#if SIZEOF_LONG == 8
+#if SIZEOF_UNSIGNED_LONG == 8
 # define FILL(n, cp)                                                       \
     switch (n) {                                                           \
     case 15:(cp)[14] = 0xff; case 14:(cp)[13] = 0xff; case 13: (cp)[12] = 0xff;\
 # define FILL(n, cp)                                                       \
     switch (n) {                                                           \
     case 15:(cp)[14] = 0xff; case 14:(cp)[13] = 0xff; case 13: (cp)[12] = 0xff;\
@@ -450,6 +453,13 @@ _TIFFFax3fillruns(unsigned char* buf, uint32* runs, uint32* erun, uint32 lastx)
 #undef ZERO
 #undef FILL
 
 #undef ZERO
 #undef FILL
 
+static int
+Fax3FixupTags(TIFF* tif)
+{
+       (void) tif;
+       return (1);
+}
+
 /*
  * Setup G3/G4-related compression/decompression state
  * before data is processed.  This routine is called once
 /*
  * Setup G3/G4-related compression/decompression state
  * before data is processed.  This routine is called once
@@ -460,14 +470,16 @@ _TIFFFax3fillruns(unsigned char* buf, uint32* runs, uint32* erun, uint32 lastx)
 static int
 Fax3SetupState(TIFF* tif)
 {
 static int
 Fax3SetupState(TIFF* tif)
 {
+       static const char module[] = "Fax3SetupState";
        TIFFDirectory* td = &tif->tif_dir;
        Fax3BaseState* sp = Fax3State(tif);
        int needsRefLine;
        Fax3CodecState* dsp = (Fax3CodecState*) Fax3State(tif);
        TIFFDirectory* td = &tif->tif_dir;
        Fax3BaseState* sp = Fax3State(tif);
        int needsRefLine;
        Fax3CodecState* dsp = (Fax3CodecState*) Fax3State(tif);
-       uint32 rowbytes, rowpixels, nruns;
+       tmsize_t rowbytes;
+       uint32 rowpixels, nruns;
 
        if (td->td_bitspersample != 1) {
 
        if (td->td_bitspersample != 1) {
-               TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+               TIFFErrorExt(tif->tif_clientdata, module,
                    "Bits/sample must be 1 for Group 3/4 encoding/decoding");
                return (0);
        }
                    "Bits/sample must be 1 for Group 3/4 encoding/decoding");
                return (0);
        }
@@ -481,8 +493,8 @@ Fax3SetupState(TIFF* tif)
                rowbytes = TIFFScanlineSize(tif);
                rowpixels = td->td_imagewidth;
        }
                rowbytes = TIFFScanlineSize(tif);
                rowpixels = td->td_imagewidth;
        }
-       sp->rowbytes = (uint32) rowbytes;
-       sp->rowpixels = (uint32) rowpixels;
+       sp->rowbytes = rowbytes;
+       sp->rowpixels = rowpixels;
        /*
         * Allocate any additional space required for decoding/encoding.
         */
        /*
         * Allocate any additional space required for decoding/encoding.
         */
@@ -491,15 +503,32 @@ Fax3SetupState(TIFF* tif)
            td->td_compression == COMPRESSION_CCITTFAX4
        );
 
            td->td_compression == COMPRESSION_CCITTFAX4
        );
 
-       nruns = needsRefLine ? 2*TIFFroundup(rowpixels,32) : rowpixels;
-
-       dsp->runs = (uint32*) _TIFFCheckMalloc(tif, 2*nruns+3, sizeof (uint32),
-                                         "for Group 3/4 run arrays");
+       /*
+         Assure that allocation computations do not overflow.
+         
+         TIFFroundup and TIFFSafeMultiply return zero on integer overflow
+       */
+       dsp->runs=(uint32*) NULL;
+       nruns = TIFFroundup_32(rowpixels,32);
+       if (needsRefLine) {
+               nruns = TIFFSafeMultiply(uint32,nruns,2);
+       }
+       if ((nruns == 0) || (TIFFSafeMultiply(uint32,nruns,2) == 0)) {
+               TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+                            "Row pixels integer overflow (rowpixels %u)",
+                            rowpixels);
+               return (0);
+       }
+       dsp->runs = (uint32*) _TIFFCheckMalloc(tif,
+                                              TIFFSafeMultiply(uint32,nruns,2),
+                                              sizeof (uint32),
+                                              "for Group 3/4 run arrays");
        if (dsp->runs == NULL)
                return (0);
        if (dsp->runs == NULL)
                return (0);
+       memset( dsp->runs, 0, TIFFSafeMultiply(uint32,nruns,2)*sizeof(uint32));
        dsp->curruns = dsp->runs;
        if (needsRefLine)
        dsp->curruns = dsp->runs;
        if (needsRefLine)
-               dsp->refruns = dsp->runs + (nruns>>1);
+               dsp->refruns = dsp->runs + nruns;
        else
                dsp->refruns = NULL;
        if (td->td_compression == COMPRESSION_CCITTFAX3
        else
                dsp->refruns = NULL;
        if (td->td_compression == COMPRESSION_CCITTFAX3
@@ -520,9 +549,8 @@ Fax3SetupState(TIFF* tif)
                 */
                esp->refline = (unsigned char*) _TIFFmalloc(rowbytes);
                if (esp->refline == NULL) {
                 */
                esp->refline = (unsigned char*) _TIFFmalloc(rowbytes);
                if (esp->refline == NULL) {
-                       TIFFErrorExt(tif->tif_clientdata, "Fax3SetupState",
-                           "%s: No space for Group 3/4 reference line",
-                           tif->tif_name);
+                       TIFFErrorExt(tif->tif_clientdata, module,
+                           "No space for Group 3/4 reference line");
                        return (0);
                }
        } else                                  /* 1d encoding */
                        return (0);
                }
        } else                                  /* 1d encoding */
@@ -538,14 +566,14 @@ Fax3SetupState(TIFF* tif)
 #define        Fax3FlushBits(tif, sp) {                                \
        if ((tif)->tif_rawcc >= (tif)->tif_rawdatasize)         \
                (void) TIFFFlushData1(tif);                     \
 #define        Fax3FlushBits(tif, sp) {                                \
        if ((tif)->tif_rawcc >= (tif)->tif_rawdatasize)         \
                (void) TIFFFlushData1(tif);                     \
-       *(tif)->tif_rawcp++ = (tidataval_t) (sp)->data;         \
+       *(tif)->tif_rawcp++ = (uint8) (sp)->data;               \
        (tif)->tif_rawcc++;                                     \
        (sp)->data = 0, (sp)->bit = 8;                          \
 }
 #define        _FlushBits(tif) {                                       \
        if ((tif)->tif_rawcc >= (tif)->tif_rawdatasize)         \
                (void) TIFFFlushData1(tif);                     \
        (tif)->tif_rawcc++;                                     \
        (sp)->data = 0, (sp)->bit = 8;                          \
 }
 #define        _FlushBits(tif) {                                       \
        if ((tif)->tif_rawcc >= (tif)->tif_rawdatasize)         \
                (void) TIFFFlushData1(tif);                     \
-       *(tif)->tif_rawcp++ = (tidataval_t) data;               \
+       *(tif)->tif_rawcp++ = (uint8) data;             \
        (tif)->tif_rawcc++;                                     \
        data = 0, bit = 8;                                      \
 }
        (tif)->tif_rawcc++;                                     \
        data = 0, bit = 8;                                      \
 }
@@ -557,6 +585,7 @@ static const int _msbmask[9] =
                length -= bit;                                  \
                _FlushBits(tif);                                \
        }                                                       \
                length -= bit;                                  \
                _FlushBits(tif);                                \
        }                                                       \
+        assert( length < 9 );                                   \
        data |= (bits & _msbmask[length]) << (bit - length);    \
        bit -= length;                                          \
        if (bit == 0)                                           \
        data |= (bits & _msbmask[length]) << (bit - length);    \
        bit -= length;                                          \
        if (bit == 0)                                           \
@@ -684,7 +713,7 @@ Fax3PutEOL(TIFF* tif)
  * Reset encoding state at the start of a strip.
  */
 static int
  * Reset encoding state at the start of a strip.
  */
 static int
-Fax3PreEncode(TIFF* tif, tsample_t s)
+Fax3PreEncode(TIFF* tif, uint16 s)
 {
        Fax3CodecState* sp = EncoderState(tif);
 
 {
        Fax3CodecState* sp = EncoderState(tif);
 
@@ -718,6 +747,7 @@ Fax3PreEncode(TIFF* tif, tsample_t s)
                sp->k = sp->maxk-1;
        } else
                sp->k = sp->maxk = 0;
                sp->k = sp->maxk-1;
        } else
                sp->k = sp->maxk = 0;
+       sp->line = 0;
        return (1);
 }
 
        return (1);
 }
 
@@ -1004,12 +1034,17 @@ Fax3Encode2DRow(TIFF* tif, unsigned char* bp, unsigned char* rp, uint32 bits)
  * Encode a buffer of pixels.
  */
 static int
  * Encode a buffer of pixels.
  */
 static int
-Fax3Encode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+Fax3Encode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 {
 {
+       static const char module[] = "Fax3Encode";
        Fax3CodecState* sp = EncoderState(tif);
        Fax3CodecState* sp = EncoderState(tif);
-
        (void) s;
        (void) s;
-       while ((long)cc > 0) {
+       if (cc % sp->b.rowbytes)
+       {
+               TIFFErrorExt(tif->tif_clientdata, module, "Fractional scanlines cannot be written");
+               return (0);
+       }
+       while (cc > 0) {
                if ((sp->b.mode & FAXMODE_NOEOL) == 0)
                        Fax3PutEOL(tif);
                if (is2DEncoding(sp)) {
                if ((sp->b.mode & FAXMODE_NOEOL) == 0)
                        Fax3PutEOL(tif);
                if (is2DEncoding(sp)) {
@@ -1019,7 +1054,7 @@ Fax3Encode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
                                sp->tag = G3_2D;
                        } else {
                                if (!Fax3Encode2DRow(tif, bp, sp->refline,
                                sp->tag = G3_2D;
                        } else {
                                if (!Fax3Encode2DRow(tif, bp, sp->refline,
-                                                     sp->b.rowpixels))
+                                   sp->b.rowpixels))
                                        return (0);
                                sp->k--;
                        }
                                        return (0);
                                sp->k--;
                        }
@@ -1074,14 +1109,13 @@ Fax3Cleanup(TIFF* tif)
 
        tif->tif_tagmethods.vgetfield = sp->b.vgetparent;
        tif->tif_tagmethods.vsetfield = sp->b.vsetparent;
 
        tif->tif_tagmethods.vgetfield = sp->b.vgetparent;
        tif->tif_tagmethods.vsetfield = sp->b.vsetparent;
+       tif->tif_tagmethods.printdir = sp->b.printdir;
 
        if (sp->runs)
                _TIFFfree(sp->runs);
        if (sp->refline)
                _TIFFfree(sp->refline);
 
 
        if (sp->runs)
                _TIFFfree(sp->runs);
        if (sp->refline)
                _TIFFfree(sp->refline);
 
-       if (Fax3State(tif)->subaddress)
-               _TIFFfree(Fax3State(tif)->subaddress);
        _TIFFfree(tif->tif_data);
        tif->tif_data = NULL;
 
        _TIFFfree(tif->tif_data);
        tif->tif_data = NULL;
 
@@ -1091,106 +1125,77 @@ Fax3Cleanup(TIFF* tif)
 #define        FIELD_BADFAXLINES       (FIELD_CODEC+0)
 #define        FIELD_CLEANFAXDATA      (FIELD_CODEC+1)
 #define        FIELD_BADFAXRUN         (FIELD_CODEC+2)
 #define        FIELD_BADFAXLINES       (FIELD_CODEC+0)
 #define        FIELD_CLEANFAXDATA      (FIELD_CODEC+1)
 #define        FIELD_BADFAXRUN         (FIELD_CODEC+2)
-#define        FIELD_RECVPARAMS        (FIELD_CODEC+3)
-#define        FIELD_SUBADDRESS        (FIELD_CODEC+4)
-#define        FIELD_RECVTIME          (FIELD_CODEC+5)
-#define        FIELD_FAXDCS            (FIELD_CODEC+6)
 
 #define        FIELD_OPTIONS           (FIELD_CODEC+7)
 
 
 #define        FIELD_OPTIONS           (FIELD_CODEC+7)
 
-static const TIFFFieldInfo faxFieldInfo[] = {
-    { TIFFTAG_FAXMODE,          0, 0,  TIFF_ANY,       FIELD_PSEUDO,
-      FALSE,   FALSE,  "FaxMode" },
-    { TIFFTAG_FAXFILLFUNC,      0, 0,  TIFF_ANY,       FIELD_PSEUDO,
-      FALSE,   FALSE,  "FaxFillFunc" },
-    { TIFFTAG_BADFAXLINES,      1, 1,  TIFF_LONG,      FIELD_BADFAXLINES,
-      TRUE,    FALSE,  "BadFaxLines" },
-    { TIFFTAG_BADFAXLINES,      1, 1,  TIFF_SHORT,     FIELD_BADFAXLINES,
-      TRUE,    FALSE,  "BadFaxLines" },
-    { TIFFTAG_CLEANFAXDATA,     1, 1,  TIFF_SHORT,     FIELD_CLEANFAXDATA,
-      TRUE,    FALSE,  "CleanFaxData" },
-    { TIFFTAG_CONSECUTIVEBADFAXLINES,1,1, TIFF_LONG,   FIELD_BADFAXRUN,
-      TRUE,    FALSE,  "ConsecutiveBadFaxLines" },
-    { TIFFTAG_CONSECUTIVEBADFAXLINES,1,1, TIFF_SHORT,  FIELD_BADFAXRUN,
-      TRUE,    FALSE,  "ConsecutiveBadFaxLines" },
-    { TIFFTAG_FAXRECVPARAMS,    1, 1, TIFF_LONG,       FIELD_RECVPARAMS,
-      TRUE,    FALSE,  "FaxRecvParams" },
-    { TIFFTAG_FAXSUBADDRESS,   -1,-1, TIFF_ASCII,      FIELD_SUBADDRESS,
-      TRUE,    FALSE,  "FaxSubAddress" },
-    { TIFFTAG_FAXRECVTIME,      1, 1, TIFF_LONG,       FIELD_RECVTIME,
-      TRUE,    FALSE,  "FaxRecvTime" },
-    { TIFFTAG_FAXDCS,          -1,-1, TIFF_ASCII,      FIELD_FAXDCS,
-      TRUE,    FALSE,  "FaxDcs" },
+static const TIFFField faxFields[] = {
+    { TIFFTAG_FAXMODE, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, FALSE, FALSE, "FaxMode", NULL },
+    { TIFFTAG_FAXFILLFUNC, 0, 0, TIFF_ANY, 0, TIFF_SETGET_OTHER, TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, FALSE, FALSE, "FaxFillFunc", NULL },
+    { TIFFTAG_BADFAXLINES, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UINT32, FIELD_BADFAXLINES, TRUE, FALSE, "BadFaxLines", NULL },
+    { TIFFTAG_CLEANFAXDATA, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UINT16, FIELD_CLEANFAXDATA, TRUE, FALSE, "CleanFaxData", NULL },
+    { TIFFTAG_CONSECUTIVEBADFAXLINES, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UINT32, FIELD_BADFAXRUN, TRUE, FALSE, "ConsecutiveBadFaxLines", NULL }};
+static const TIFFField fax3Fields[] = {
+    { TIFFTAG_GROUP3OPTIONS, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UINT32, FIELD_OPTIONS, FALSE, FALSE, "Group3Options", NULL },
 };
 };
-static const TIFFFieldInfo fax3FieldInfo[] = {
-    { TIFFTAG_GROUP3OPTIONS,    1, 1,  TIFF_LONG,      FIELD_OPTIONS,
-      FALSE,   FALSE,  "Group3Options" },
+static const TIFFField fax4Fields[] = {
+    { TIFFTAG_GROUP4OPTIONS, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UINT32, FIELD_OPTIONS, FALSE, FALSE, "Group4Options", NULL },
 };
 };
-static const TIFFFieldInfo fax4FieldInfo[] = {
-    { TIFFTAG_GROUP4OPTIONS,    1, 1,  TIFF_LONG,      FIELD_OPTIONS,
-      FALSE,   FALSE,  "Group4Options" },
-};
-#define        N(a)    (sizeof (a) / sizeof (a[0]))
 
 static int
 
 static int
-Fax3VSetField(TIFF* tif, ttag_t tag, va_list ap)
+Fax3VSetField(TIFF* tif, uint32 tag, va_list ap)
 {
        Fax3BaseState* sp = Fax3State(tif);
 {
        Fax3BaseState* sp = Fax3State(tif);
+       const TIFFField* fip;
 
        assert(sp != 0);
        assert(sp->vsetparent != 0);
 
        switch (tag) {
        case TIFFTAG_FAXMODE:
 
        assert(sp != 0);
        assert(sp->vsetparent != 0);
 
        switch (tag) {
        case TIFFTAG_FAXMODE:
-               sp->mode = va_arg(ap, int);
-               return (1);                     /* NB: pseudo tag */
+               sp->mode = (int) va_arg(ap, int);
+               return 1;                       /* NB: pseudo tag */
        case TIFFTAG_FAXFILLFUNC:
                DecoderState(tif)->fill = va_arg(ap, TIFFFaxFillFunc);
        case TIFFTAG_FAXFILLFUNC:
                DecoderState(tif)->fill = va_arg(ap, TIFFFaxFillFunc);
-               return (1);                     /* NB: pseudo tag */
+               return 1;                       /* NB: pseudo tag */
        case TIFFTAG_GROUP3OPTIONS:
                /* XXX: avoid reading options if compression mismatches. */
                if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX3)
        case TIFFTAG_GROUP3OPTIONS:
                /* XXX: avoid reading options if compression mismatches. */
                if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX3)
-                       sp->groupoptions = va_arg(ap, uint32);
+                       sp->groupoptions = (uint32) va_arg(ap, uint32);
                break;
        case TIFFTAG_GROUP4OPTIONS:
                /* XXX: avoid reading options if compression mismatches. */
                if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX4)
                break;
        case TIFFTAG_GROUP4OPTIONS:
                /* XXX: avoid reading options if compression mismatches. */
                if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX4)
-                       sp->groupoptions = va_arg(ap, uint32);
+                       sp->groupoptions = (uint32) va_arg(ap, uint32);
                break;
        case TIFFTAG_BADFAXLINES:
                break;
        case TIFFTAG_BADFAXLINES:
-               sp->badfaxlines = va_arg(ap, uint32);
+               sp->badfaxlines = (uint32) va_arg(ap, uint32);
                break;
        case TIFFTAG_CLEANFAXDATA:
                break;
        case TIFFTAG_CLEANFAXDATA:
-               sp->cleanfaxdata = (uint16) va_arg(ap, int);
+               sp->cleanfaxdata = (uint16) va_arg(ap, uint16_vap);
                break;
        case TIFFTAG_CONSECUTIVEBADFAXLINES:
                break;
        case TIFFTAG_CONSECUTIVEBADFAXLINES:
-               sp->badfaxrun = va_arg(ap, uint32);
-               break;
-       case TIFFTAG_FAXRECVPARAMS:
-               sp->recvparams = va_arg(ap, uint32);
-               break;
-       case TIFFTAG_FAXSUBADDRESS:
-               _TIFFsetString(&sp->subaddress, va_arg(ap, char*));
-               break;
-       case TIFFTAG_FAXRECVTIME:
-               sp->recvtime = va_arg(ap, uint32);
-               break;
-       case TIFFTAG_FAXDCS:
-               _TIFFsetString(&sp->faxdcs, va_arg(ap, char*));
+               sp->badfaxrun = (uint32) va_arg(ap, uint32);
                break;
        default:
                return (*sp->vsetparent)(tif, tag, ap);
        }
                break;
        default:
                return (*sp->vsetparent)(tif, tag, ap);
        }
-       TIFFSetFieldBit(tif, _TIFFFieldWithTag(tif, tag)->field_bit);
+       
+       if ((fip = TIFFFieldWithTag(tif, tag)))
+               TIFFSetFieldBit(tif, fip->field_bit);
+       else
+               return 0;
+
        tif->tif_flags |= TIFF_DIRTYDIRECT;
        tif->tif_flags |= TIFF_DIRTYDIRECT;
-       return (1);
+       return 1;
 }
 
 static int
 }
 
 static int
-Fax3VGetField(TIFF* tif, ttag_t tag, va_list ap)
+Fax3VGetField(TIFF* tif, uint32 tag, va_list ap)
 {
        Fax3BaseState* sp = Fax3State(tif);
 
 {
        Fax3BaseState* sp = Fax3State(tif);
 
+       assert(sp != 0);
+
        switch (tag) {
        case TIFFTAG_FAXMODE:
                *va_arg(ap, int*) = sp->mode;
        switch (tag) {
        case TIFFTAG_FAXMODE:
                *va_arg(ap, int*) = sp->mode;
@@ -1211,18 +1216,6 @@ Fax3VGetField(TIFF* tif, ttag_t tag, va_list ap)
        case TIFFTAG_CONSECUTIVEBADFAXLINES:
                *va_arg(ap, uint32*) = sp->badfaxrun;
                break;
        case TIFFTAG_CONSECUTIVEBADFAXLINES:
                *va_arg(ap, uint32*) = sp->badfaxrun;
                break;
-       case TIFFTAG_FAXRECVPARAMS:
-               *va_arg(ap, uint32*) = sp->recvparams;
-               break;
-       case TIFFTAG_FAXSUBADDRESS:
-               *va_arg(ap, char**) = sp->subaddress;
-               break;
-       case TIFFTAG_FAXRECVTIME:
-               *va_arg(ap, uint32*) = sp->recvtime;
-               break;
-       case TIFFTAG_FAXDCS:
-               *va_arg(ap, char**) = sp->faxdcs;
-               break;
        default:
                return (*sp->vgetparent)(tif, tag, ap);
        }
        default:
                return (*sp->vgetparent)(tif, tag, ap);
        }
@@ -1234,6 +1227,8 @@ Fax3PrintDir(TIFF* tif, FILE* fd, long flags)
 {
        Fax3BaseState* sp = Fax3State(tif);
 
 {
        Fax3BaseState* sp = Fax3State(tif);
 
+       assert(sp != 0);
+
        (void) flags;
        if (TIFFFieldSet(tif,FIELD_OPTIONS)) {
                const char* sep = " ";
        (void) flags;
        if (TIFFFieldSet(tif,FIELD_OPTIONS)) {
                const char* sep = " ";
@@ -1277,32 +1272,34 @@ Fax3PrintDir(TIFF* tif, FILE* fd, long flags)
        if (TIFFFieldSet(tif,FIELD_BADFAXRUN))
                fprintf(fd, "  Consecutive Bad Fax Lines: %lu\n",
                    (unsigned long) sp->badfaxrun);
        if (TIFFFieldSet(tif,FIELD_BADFAXRUN))
                fprintf(fd, "  Consecutive Bad Fax Lines: %lu\n",
                    (unsigned long) sp->badfaxrun);
-       if (TIFFFieldSet(tif,FIELD_RECVPARAMS))
-               fprintf(fd, "  Fax Receive Parameters: %08lx\n",
-                  (unsigned long) sp->recvparams);
-       if (TIFFFieldSet(tif,FIELD_SUBADDRESS))
-               fprintf(fd, "  Fax SubAddress: %s\n", sp->subaddress);
-       if (TIFFFieldSet(tif,FIELD_RECVTIME))
-               fprintf(fd, "  Fax Receive Time: %lu secs\n",
-                   (unsigned long) sp->recvtime);
-       if (TIFFFieldSet(tif,FIELD_FAXDCS))
-               fprintf(fd, "  Fax DCS: %s\n", sp->faxdcs);
+       if (sp->printdir)
+               (*sp->printdir)(tif, fd, flags);
 }
 
 static int
 InitCCITTFax3(TIFF* tif)
 {
 }
 
 static int
 InitCCITTFax3(TIFF* tif)
 {
+       static const char module[] = "InitCCITTFax3";
        Fax3BaseState* sp;
 
        Fax3BaseState* sp;
 
+       /*
+        * Merge codec-specific tag information.
+        */
+       if (!_TIFFMergeFields(tif, faxFields, TIFFArrayCount(faxFields))) {
+               TIFFErrorExt(tif->tif_clientdata, "InitCCITTFax3",
+                       "Merging common CCITT Fax codec-specific tags failed");
+               return 0;
+       }
+
        /*
         * Allocate state block so tag methods have storage to record values.
         */
        /*
         * Allocate state block so tag methods have storage to record values.
         */
-       tif->tif_data = (tidata_t)
+       tif->tif_data = (uint8*)
                _TIFFmalloc(sizeof (Fax3CodecState));
 
        if (tif->tif_data == NULL) {
                _TIFFmalloc(sizeof (Fax3CodecState));
 
        if (tif->tif_data == NULL) {
-               TIFFErrorExt(tif->tif_clientdata, "TIFFInitCCITTFax3",
-                   "%s: No space for state block", tif->tif_name);
+               TIFFErrorExt(tif->tif_clientdata, module,
+                   "No space for state block");
                return (0);
        }
 
                return (0);
        }
 
@@ -1310,19 +1307,15 @@ InitCCITTFax3(TIFF* tif)
         sp->rw_mode = tif->tif_mode;
 
        /*
         sp->rw_mode = tif->tif_mode;
 
        /*
-        * Merge codec-specific tag information and
-        * override parent get/set field methods.
+        * Override parent get/set field methods.
         */
         */
-       _TIFFMergeFieldInfo(tif, faxFieldInfo, N(faxFieldInfo));
        sp->vgetparent = tif->tif_tagmethods.vgetfield;
        tif->tif_tagmethods.vgetfield = Fax3VGetField; /* hook for codec tags */
        sp->vsetparent = tif->tif_tagmethods.vsetfield;
        tif->tif_tagmethods.vsetfield = Fax3VSetField; /* hook for codec tags */
        sp->vgetparent = tif->tif_tagmethods.vgetfield;
        tif->tif_tagmethods.vgetfield = Fax3VGetField; /* hook for codec tags */
        sp->vsetparent = tif->tif_tagmethods.vsetfield;
        tif->tif_tagmethods.vsetfield = Fax3VSetField; /* hook for codec tags */
+       sp->printdir = tif->tif_tagmethods.printdir;
        tif->tif_tagmethods.printdir = Fax3PrintDir;   /* hook for codec tags */
        sp->groupoptions = 0;   
        tif->tif_tagmethods.printdir = Fax3PrintDir;   /* hook for codec tags */
        sp->groupoptions = 0;   
-       sp->recvparams = 0;
-       sp->subaddress = NULL;
-       sp->faxdcs = NULL;
 
        if (sp->rw_mode == O_RDONLY) /* FIXME: improve for in place update */
                tif->tif_flags |= TIFF_NOBITREV; /* decoder does bit reversal */
 
        if (sp->rw_mode == O_RDONLY) /* FIXME: improve for in place update */
                tif->tif_flags |= TIFF_NOBITREV; /* decoder does bit reversal */
@@ -1333,6 +1326,7 @@ InitCCITTFax3(TIFF* tif)
        /*
         * Install codec methods.
         */
        /*
         * Install codec methods.
         */
+       tif->tif_fixuptags = Fax3FixupTags;
        tif->tif_setupdecode = Fax3SetupState;
        tif->tif_predecode = Fax3PreDecode;
        tif->tif_decoderow = Fax3Decode1D;
        tif->tif_setupdecode = Fax3SetupState;
        tif->tif_predecode = Fax3PreDecode;
        tif->tif_decoderow = Fax3Decode1D;
@@ -1355,14 +1349,22 @@ TIFFInitCCITTFax3(TIFF* tif, int scheme)
 {
        (void) scheme;
        if (InitCCITTFax3(tif)) {
 {
        (void) scheme;
        if (InitCCITTFax3(tif)) {
-               _TIFFMergeFieldInfo(tif, fax3FieldInfo, N(fax3FieldInfo));
+               /*
+                * Merge codec-specific tag information.
+                */
+               if (!_TIFFMergeFields(tif, fax3Fields,
+                                     TIFFArrayCount(fax3Fields))) {
+                       TIFFErrorExt(tif->tif_clientdata, "TIFFInitCCITTFax3",
+                       "Merging CCITT Fax 3 codec-specific tags failed");
+                       return 0;
+               }
 
                /*
                 * The default format is Class/F-style w/o RTC.
                 */
                return TIFFSetField(tif, TIFFTAG_FAXMODE, FAXMODE_CLASSF);
        } else
 
                /*
                 * The default format is Class/F-style w/o RTC.
                 */
                return TIFFSetField(tif, TIFFTAG_FAXMODE, FAXMODE_CLASSF);
        } else
-               return (0);
+               return 01;
 }
 
 /*
 }
 
 /*
@@ -1370,19 +1372,22 @@ TIFFInitCCITTFax3(TIFF* tif, int scheme)
  * Compression Scheme Support.
  */
 
  * Compression Scheme Support.
  */
 
-#define        SWAP(t,a,b)     { t x; x = (a); (a) = (b); (b) = x; }
+#define SWAP(t,a,b) { t x; x = (a); (a) = (b); (b) = x; }
 /*
  * Decode the requested amount of G4-encoded data.
  */
 static int
 /*
  * Decode the requested amount of G4-encoded data.
  */
 static int
-Fax4Decode(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s)
+Fax4Decode(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s)
 {
        DECLARE_STATE_2D(tif, sp, "Fax4Decode");
 {
        DECLARE_STATE_2D(tif, sp, "Fax4Decode");
-        int line = 0;
-
        (void) s;
        (void) s;
+       if (occ % sp->b.rowbytes)
+       {
+               TIFFErrorExt(tif->tif_clientdata, module, "Fractional scanlines cannot be read");
+               return (-1);
+       }
        CACHE_STATE(tif, sp);
        CACHE_STATE(tif, sp);
-       while ((long)occ > 0) {
+       while (occ > 0) {
                a0 = 0;
                RunLength = 0;
                pa = thisrun = sp->curruns;
                a0 = 0;
                RunLength = 0;
                pa = thisrun = sp->curruns;
@@ -1401,19 +1406,19 @@ Fax4Decode(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s)
                SWAP(uint32*, sp->curruns, sp->refruns);
                buf += sp->b.rowbytes;
                occ -= sp->b.rowbytes;
                SWAP(uint32*, sp->curruns, sp->refruns);
                buf += sp->b.rowbytes;
                occ -= sp->b.rowbytes;
-                line++;
+               sp->line++;
                continue;
        EOFG4:
                 NeedBits16( 13, BADG4 );
         BADG4:
 #ifdef FAX3_DEBUG
                 if( GetBits(13) != 0x1001 )
                continue;
        EOFG4:
                 NeedBits16( 13, BADG4 );
         BADG4:
 #ifdef FAX3_DEBUG
                 if( GetBits(13) != 0x1001 )
-                    fputs( "Bad RTC\n", stderr );
+                    fputs( "Bad EOFB\n", stderr );
 #endif                
                 ClrBits( 13 );
                (*sp->fill)(buf, thisrun, pa, lastx);
                UNCACHE_STATE(tif, sp);
 #endif                
                 ClrBits( 13 );
                (*sp->fill)(buf, thisrun, pa, lastx);
                UNCACHE_STATE(tif, sp);
-               return (-1);
+               return ( sp->line ? 1 : -1);    /* don't error on badly-terminated strips */
        }
        UNCACHE_STATE(tif, sp);
        return (1);
        }
        UNCACHE_STATE(tif, sp);
        return (1);
@@ -1424,12 +1429,17 @@ Fax4Decode(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s)
  * Encode the requested amount of data.
  */
 static int
  * Encode the requested amount of data.
  */
 static int
-Fax4Encode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+Fax4Encode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 {
 {
+       static const char module[] = "Fax4Encode";
        Fax3CodecState *sp = EncoderState(tif);
        Fax3CodecState *sp = EncoderState(tif);
-
        (void) s;
        (void) s;
-       while ((long)cc > 0) {
+       if (cc % sp->b.rowbytes)
+       {
+               TIFFErrorExt(tif->tif_clientdata, module, "Fractional scanlines cannot be written");
+               return (0);
+       }
+       while (cc > 0) {
                if (!Fax3Encode2DRow(tif, bp, sp->refline, sp->b.rowpixels))
                        return (0);
                _TIFFmemcpy(sp->refline, bp, sp->b.rowbytes);
                if (!Fax3Encode2DRow(tif, bp, sp->refline, sp->b.rowpixels))
                        return (0);
                _TIFFmemcpy(sp->refline, bp, sp->b.rowbytes);
@@ -1457,7 +1467,15 @@ TIFFInitCCITTFax4(TIFF* tif, int scheme)
 {
        (void) scheme;
        if (InitCCITTFax3(tif)) {               /* reuse G3 support */
 {
        (void) scheme;
        if (InitCCITTFax3(tif)) {               /* reuse G3 support */
-               _TIFFMergeFieldInfo(tif, fax4FieldInfo, N(fax4FieldInfo));
+               /*
+                * Merge codec-specific tag information.
+                */
+               if (!_TIFFMergeFields(tif, fax4Fields,
+                                     TIFFArrayCount(fax4Fields))) {
+                       TIFFErrorExt(tif->tif_clientdata, "TIFFInitCCITTFax4",
+                       "Merging CCITT Fax 4 codec-specific tags failed");
+                       return 0;
+               }
 
                tif->tif_decoderow = Fax4Decode;
                tif->tif_decodestrip = Fax4Decode;
 
                tif->tif_decoderow = Fax4Decode;
                tif->tif_decodestrip = Fax4Decode;
@@ -1483,16 +1501,19 @@ TIFFInitCCITTFax4(TIFF* tif, int scheme)
  * Decode the requested amount of RLE-encoded data.
  */
 static int
  * Decode the requested amount of RLE-encoded data.
  */
 static int
-Fax3DecodeRLE(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s)
+Fax3DecodeRLE(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s)
 {
        DECLARE_STATE(tif, sp, "Fax3DecodeRLE");
        int mode = sp->b.mode;
 {
        DECLARE_STATE(tif, sp, "Fax3DecodeRLE");
        int mode = sp->b.mode;
-        int line = 0;
-
        (void) s;
        (void) s;
+       if (occ % sp->b.rowbytes)
+       {
+               TIFFErrorExt(tif->tif_clientdata, module, "Fractional scanlines cannot be read");
+               return (-1);
+       }
        CACHE_STATE(tif, sp);
        thisrun = sp->curruns;
        CACHE_STATE(tif, sp);
        thisrun = sp->curruns;
-       while ((long)occ > 0) {
+       while (occ > 0) {
                a0 = 0;
                RunLength = 0;
                pa = thisrun;
                a0 = 0;
                RunLength = 0;
                pa = thisrun;
@@ -1517,7 +1538,7 @@ Fax3DecodeRLE(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s)
                }
                buf += sp->b.rowbytes;
                occ -= sp->b.rowbytes;
                }
                buf += sp->b.rowbytes;
                occ -= sp->b.rowbytes;
-                line++;
+               sp->line++;
                continue;
        EOFRLE:                         /* premature EOF */
                (*sp->fill)(buf, thisrun, pa, lastx);
                continue;
        EOFRLE:                         /* premature EOF */
                (*sp->fill)(buf, thisrun, pa, lastx);
@@ -1552,7 +1573,7 @@ TIFFInitCCITTRLEW(TIFF* tif, int scheme)
        if (InitCCITTFax3(tif)) {               /* reuse G3 support */
                tif->tif_decoderow = Fax3DecodeRLE;
                tif->tif_decodestrip = Fax3DecodeRLE;
        if (InitCCITTFax3(tif)) {               /* reuse G3 support */
                tif->tif_decoderow = Fax3DecodeRLE;
                tif->tif_decodestrip = Fax3DecodeRLE;
-               tif->tif_decodetile = Fax3DecodeRLE;
+               tif->tif_decodetile = Fax3DecodeRLE;  
                /*
                 * Suppress RTC+EOLs when encoding and word-align data.
                 */
                /*
                 * Suppress RTC+EOLs when encoding and word-align data.
                 */
@@ -1564,3 +1585,10 @@ TIFFInitCCITTRLEW(TIFF* tif, int scheme)
 #endif /* CCITT_SUPPORT */
 
 /* vim: set ts=8 sts=8 sw=8 noet: */
 #endif /* CCITT_SUPPORT */
 
 /* vim: set ts=8 sts=8 sw=8 noet: */
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 8
+ * fill-column: 78
+ * End:
+ */