Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/tiff/libtiff/tif_packbits.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 1988-1997 Sam Leffler
3
 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
4
 *
5
 * Permission to use, copy, modify, distribute, and sell this software and
6
 * its documentation for any purpose is hereby granted without fee, provided
7
 * that (i) the above copyright notices and this permission notice appear in
8
 * all copies of the software and related documentation, and (ii) the names of
9
 * Sam Leffler and Silicon Graphics may not be used in any advertising or
10
 * publicity relating to the software without the specific, prior written
11
 * permission of Sam Leffler and Silicon Graphics.
12
 *
13
 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
14
 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15
 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
16
 *
17
 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
18
 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20
 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21
 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22
 * OF THIS SOFTWARE.
23
 */
24
25
#include "tiffiop.h"
26
#ifdef PACKBITS_SUPPORT
27
/*
28
 * TIFF Library.
29
 *
30
 * PackBits Compression Algorithm Support
31
 */
32
#include <stdio.h>
33
34
static int PackBitsPreEncode(TIFF *tif, uint16_t s)
35
0
{
36
0
    (void)s;
37
38
0
    tif->tif_data = (uint8_t *)_TIFFmallocExt(tif, sizeof(tmsize_t));
39
0
    if (tif->tif_data == NULL)
40
0
        return (0);
41
    /*
42
     * Calculate the scanline/tile-width size in bytes.
43
     */
44
0
    if (isTiled(tif))
45
0
        *(tmsize_t *)tif->tif_data = TIFFTileRowSize(tif);
46
0
    else
47
0
        *(tmsize_t *)tif->tif_data = TIFFScanlineSize(tif);
48
0
    return (1);
49
0
}
50
51
static int PackBitsPostEncode(TIFF *tif)
52
0
{
53
0
    if (tif->tif_data)
54
0
        _TIFFfreeExt(tif, tif->tif_data);
55
0
    return (1);
56
0
}
57
58
/*
59
 * Encode a run of pixels.
60
 */
61
static int PackBitsEncode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
62
0
{
63
0
    unsigned char *bp = (unsigned char *)buf;
64
0
    uint8_t *op;
65
0
    uint8_t *ep;
66
0
    uint8_t *lastliteral;
67
0
    long n, slop;
68
0
    int b;
69
0
    enum
70
0
    {
71
0
        BASE,
72
0
        LITERAL,
73
0
        RUN,
74
0
        LITERAL_RUN
75
0
    } state;
76
77
0
    (void)s;
78
0
    op = tif->tif_rawcp;
79
0
    ep = tif->tif_rawdata + tif->tif_rawdatasize;
80
0
    state = BASE;
81
0
    lastliteral = 0;
82
0
    while (cc > 0)
83
0
    {
84
        /*
85
         * Find the longest string of identical bytes.
86
         */
87
0
        b = *bp++;
88
0
        cc--;
89
0
        n = 1;
90
0
        for (; cc > 0 && b == *bp; cc--, bp++)
91
0
            n++;
92
0
    again:
93
0
        if (op + 2 >= ep)
94
0
        { /* insure space for new data */
95
            /*
96
             * Be careful about writing the last
97
             * literal.  Must write up to that point
98
             * and then copy the remainder to the
99
             * front of the buffer.
100
             */
101
0
            if (state == LITERAL || state == LITERAL_RUN)
102
0
            {
103
0
                slop = (long)(op - lastliteral);
104
0
                tif->tif_rawcc += (tmsize_t)(lastliteral - tif->tif_rawcp);
105
0
                if (!TIFFFlushData1(tif))
106
0
                    return (0);
107
0
                op = tif->tif_rawcp;
108
0
                while (slop-- > 0)
109
0
                    *op++ = *lastliteral++;
110
0
                lastliteral = tif->tif_rawcp;
111
0
            }
112
0
            else
113
0
            {
114
0
                tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp);
115
0
                if (!TIFFFlushData1(tif))
116
0
                    return (0);
117
0
                op = tif->tif_rawcp;
118
0
            }
119
0
        }
120
0
        switch (state)
121
0
        {
122
0
            case BASE: /* initial state, set run/literal */
123
0
                if (n > 1)
124
0
                {
125
0
                    state = RUN;
126
0
                    if (n > 128)
127
0
                    {
128
0
                        *op++ = (uint8_t)-127;
129
0
                        *op++ = (uint8_t)b;
130
0
                        n -= 128;
131
0
                        goto again;
132
0
                    }
133
0
                    *op++ = (uint8_t)(-(n - 1));
134
0
                    *op++ = (uint8_t)b;
135
0
                }
136
0
                else
137
0
                {
138
0
                    lastliteral = op;
139
0
                    *op++ = 0;
140
0
                    *op++ = (uint8_t)b;
141
0
                    state = LITERAL;
142
0
                }
143
0
                break;
144
0
            case LITERAL: /* last object was literal string */
145
0
                if (n > 1)
146
0
                {
147
0
                    state = LITERAL_RUN;
148
0
                    if (n > 128)
149
0
                    {
150
0
                        *op++ = (uint8_t)-127;
151
0
                        *op++ = (uint8_t)b;
152
0
                        n -= 128;
153
0
                        goto again;
154
0
                    }
155
0
                    *op++ = (uint8_t)(-(n - 1)); /* encode run */
156
0
                    *op++ = (uint8_t)b;
157
0
                }
158
0
                else
159
0
                { /* extend literal */
160
0
                    if (++(*lastliteral) == 127)
161
0
                        state = BASE;
162
0
                    *op++ = (uint8_t)b;
163
0
                }
164
0
                break;
165
0
            case RUN: /* last object was run */
166
0
                if (n > 1)
167
0
                {
168
0
                    if (n > 128)
169
0
                    {
170
0
                        *op++ = (uint8_t)-127;
171
0
                        *op++ = (uint8_t)b;
172
0
                        n -= 128;
173
0
                        goto again;
174
0
                    }
175
0
                    *op++ = (uint8_t)(-(n - 1));
176
0
                    *op++ = (uint8_t)b;
177
0
                }
178
0
                else
179
0
                {
180
0
                    lastliteral = op;
181
0
                    *op++ = 0;
182
0
                    *op++ = (uint8_t)b;
183
0
                    state = LITERAL;
184
0
                }
185
0
                break;
186
0
            case LITERAL_RUN: /* literal followed by a run */
187
                /*
188
                 * Check to see if previous run should
189
                 * be converted to a literal, in which
190
                 * case we convert literal-run-literal
191
                 * to a single literal.
192
                 */
193
0
                if (n == 1 && op[-2] == (uint8_t)-1 && *lastliteral < 126)
194
0
                {
195
0
                    state = (((*lastliteral) += 2) == 127 ? BASE : LITERAL);
196
0
                    op[-2] = op[-1]; /* replicate */
197
0
                }
198
0
                else
199
0
                    state = RUN;
200
0
                goto again;
201
0
        }
202
0
    }
203
0
    tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp);
204
0
    tif->tif_rawcp = op;
205
0
    return (1);
206
0
}
207
208
/*
209
 * Encode a rectangular chunk of pixels.  We break it up
210
 * into row-sized pieces to insure that encoded runs do
211
 * not span rows.  Otherwise, there can be problems with
212
 * the decoder if data is read, for example, by scanlines
213
 * when it was encoded by strips.
214
 */
215
static int PackBitsEncodeChunk(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
216
0
{
217
0
    tmsize_t rowsize = *(tmsize_t *)tif->tif_data;
218
219
0
    while (cc > 0)
220
0
    {
221
0
        tmsize_t chunk = rowsize;
222
223
0
        if (cc < chunk)
224
0
            chunk = cc;
225
226
0
        if (PackBitsEncode(tif, bp, chunk, s) < 0)
227
0
            return (-1);
228
0
        bp += chunk;
229
0
        cc -= chunk;
230
0
    }
231
0
    return (1);
232
0
}
233
234
static int PackBitsDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
235
0
{
236
0
    static const char module[] = "PackBitsDecode";
237
0
    int8_t *bp;
238
0
    tmsize_t cc;
239
0
    long n;
240
0
    int b;
241
242
0
    (void)s;
243
0
    bp = (int8_t *)tif->tif_rawcp;
244
0
    cc = tif->tif_rawcc;
245
0
    while (cc > 0 && occ > 0)
246
0
    {
247
0
        n = (long)*bp++;
248
0
        cc--;
249
0
        if (n < 0)
250
0
        {                  /* replicate next byte -n+1 times */
251
0
            if (n == -128) /* nop */
252
0
                continue;
253
0
            n = -n + 1;
254
0
            if (occ < (tmsize_t)n)
255
0
            {
256
0
                TIFFWarningExtR(tif, module,
257
0
                                "Discarding %" TIFF_SSIZE_FORMAT
258
0
                                " bytes to avoid buffer overrun",
259
0
                                (tmsize_t)n - occ);
260
0
                n = (long)occ;
261
0
            }
262
0
            if (cc == 0)
263
0
            {
264
0
                TIFFWarningExtR(
265
0
                    tif, module,
266
0
                    "Terminating PackBitsDecode due to lack of data.");
267
0
                break;
268
0
            }
269
0
            occ -= n;
270
0
            b = *bp++;
271
0
            cc--;
272
0
            while (n-- > 0)
273
0
                *op++ = (uint8_t)b;
274
0
        }
275
0
        else
276
0
        { /* copy next n+1 bytes literally */
277
0
            if (occ < (tmsize_t)(n + 1))
278
0
            {
279
0
                TIFFWarningExtR(tif, module,
280
0
                                "Discarding %" TIFF_SSIZE_FORMAT
281
0
                                " bytes to avoid buffer overrun",
282
0
                                (tmsize_t)n - occ + 1);
283
0
                n = (long)occ - 1;
284
0
            }
285
0
            if (cc < (tmsize_t)(n + 1))
286
0
            {
287
0
                TIFFWarningExtR(
288
0
                    tif, module,
289
0
                    "Terminating PackBitsDecode due to lack of data.");
290
0
                break;
291
0
            }
292
0
            _TIFFmemcpy(op, bp, ++n);
293
0
            op += n;
294
0
            occ -= n;
295
0
            bp += n;
296
0
            cc -= n;
297
0
        }
298
0
    }
299
0
    tif->tif_rawcp = (uint8_t *)bp;
300
0
    tif->tif_rawcc = cc;
301
0
    if (occ > 0)
302
0
    {
303
0
        memset(op, 0, (size_t)occ);
304
0
        TIFFErrorExtR(tif, module, "Not enough data for scanline %" PRIu32,
305
0
                      tif->tif_row);
306
0
        return (0);
307
0
    }
308
0
    return (1);
309
0
}
310
311
int TIFFInitPackBits(TIFF *tif, int scheme)
312
0
{
313
0
    (void)scheme;
314
0
    tif->tif_decoderow = PackBitsDecode;
315
0
    tif->tif_decodestrip = PackBitsDecode;
316
0
    tif->tif_decodetile = PackBitsDecode;
317
0
    tif->tif_preencode = PackBitsPreEncode;
318
0
    tif->tif_postencode = PackBitsPostEncode;
319
0
    tif->tif_encoderow = PackBitsEncode;
320
0
    tif->tif_encodestrip = PackBitsEncodeChunk;
321
0
    tif->tif_encodetile = PackBitsEncodeChunk;
322
0
    return (1);
323
0
}
324
#endif /* PACKBITS_SUPPORT */