xref: /aosp_15_r20/external/pdfium/third_party/libtiff/tif_next.c (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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 NEXT_SUPPORT
27 /*
28  * TIFF Library.
29  *
30  * NeXT 2-bit Grey Scale Compression Algorithm Support
31  */
32 
33 #define SETPIXEL(op, v)                                                        \
34     {                                                                          \
35         switch (npixels++ & 3)                                                 \
36         {                                                                      \
37             case 0:                                                            \
38                 op[0] = (unsigned char)((v) << 6);                             \
39                 break;                                                         \
40             case 1:                                                            \
41                 op[0] |= (v) << 4;                                             \
42                 break;                                                         \
43             case 2:                                                            \
44                 op[0] |= (v) << 2;                                             \
45                 break;                                                         \
46             case 3:                                                            \
47                 *op++ |= (v);                                                  \
48                 op_offset++;                                                   \
49                 break;                                                         \
50         }                                                                      \
51     }
52 
53 #define LITERALROW 0x00
54 #define LITERALSPAN 0x40
55 #define WHITE ((1 << 2) - 1)
56 
NeXTDecode(TIFF * tif,uint8_t * buf,tmsize_t occ,uint16_t s)57 static int NeXTDecode(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s)
58 {
59     static const char module[] = "NeXTDecode";
60     unsigned char *bp, *op;
61     tmsize_t cc;
62     uint8_t *row;
63     tmsize_t scanline, n;
64 
65     (void)s;
66     /*
67      * Each scanline is assumed to start off as all
68      * white (we assume a PhotometricInterpretation
69      * of ``min-is-black'').
70      */
71     for (op = (unsigned char *)buf, cc = occ; cc-- > 0;)
72         *op++ = 0xff;
73 
74     bp = (unsigned char *)tif->tif_rawcp;
75     cc = tif->tif_rawcc;
76     scanline = tif->tif_scanlinesize;
77     if (occ % scanline)
78     {
79         TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read");
80         return (0);
81     }
82     for (row = buf; cc > 0 && occ > 0; occ -= scanline, row += scanline)
83     {
84         n = *bp++;
85         cc--;
86         switch (n)
87         {
88             case LITERALROW:
89                 /*
90                  * The entire scanline is given as literal values.
91                  */
92                 if (cc < scanline)
93                     goto bad;
94                 _TIFFmemcpy(row, bp, scanline);
95                 bp += scanline;
96                 cc -= scanline;
97                 break;
98             case LITERALSPAN:
99             {
100                 tmsize_t off;
101                 /*
102                  * The scanline has a literal span that begins at some
103                  * offset.
104                  */
105                 if (cc < 4)
106                     goto bad;
107                 off = (bp[0] * 256) + bp[1];
108                 n = (bp[2] * 256) + bp[3];
109                 if (cc < 4 + n || off + n > scanline)
110                     goto bad;
111                 _TIFFmemcpy(row + off, bp + 4, n);
112                 bp += 4 + n;
113                 cc -= 4 + n;
114                 break;
115             }
116             default:
117             {
118                 uint32_t npixels = 0, grey;
119                 tmsize_t op_offset = 0;
120                 uint32_t imagewidth = tif->tif_dir.td_imagewidth;
121                 if (isTiled(tif))
122                     imagewidth = tif->tif_dir.td_tilewidth;
123 
124                 /*
125                  * The scanline is composed of a sequence of constant
126                  * color ``runs''.  We shift into ``run mode'' and
127                  * interpret bytes as codes of the form
128                  * <color><npixels> until we've filled the scanline.
129                  */
130                 op = row;
131                 for (;;)
132                 {
133                     grey = (uint32_t)((n >> 6) & 0x3);
134                     n &= 0x3f;
135                     /*
136                      * Ensure the run does not exceed the scanline
137                      * bounds, potentially resulting in a security
138                      * issue.
139                      */
140                     while (n-- > 0 && npixels < imagewidth &&
141                            op_offset < scanline)
142                         SETPIXEL(op, grey);
143                     if (npixels >= imagewidth)
144                         break;
145                     if (op_offset >= scanline)
146                     {
147                         TIFFErrorExtR(tif, module,
148                                       "Invalid data for scanline %" PRIu32,
149                                       tif->tif_row);
150                         return (0);
151                     }
152                     if (cc == 0)
153                         goto bad;
154                     n = *bp++;
155                     cc--;
156                 }
157                 break;
158             }
159         }
160     }
161     tif->tif_rawcp = (uint8_t *)bp;
162     tif->tif_rawcc = cc;
163     return (1);
164 bad:
165     TIFFErrorExtR(tif, module, "Not enough data for scanline %" PRIu32,
166                   tif->tif_row);
167     return (0);
168 }
169 
NeXTPreDecode(TIFF * tif,uint16_t s)170 static int NeXTPreDecode(TIFF *tif, uint16_t s)
171 {
172     static const char module[] = "NeXTPreDecode";
173     TIFFDirectory *td = &tif->tif_dir;
174     (void)s;
175 
176     if (td->td_bitspersample != 2)
177     {
178         TIFFErrorExtR(tif, module, "Unsupported BitsPerSample = %" PRIu16,
179                       td->td_bitspersample);
180         return (0);
181     }
182     return (1);
183 }
184 
TIFFInitNeXT(TIFF * tif,int scheme)185 int TIFFInitNeXT(TIFF *tif, int scheme)
186 {
187     (void)scheme;
188     tif->tif_predecode = NeXTPreDecode;
189     tif->tif_decoderow = NeXTDecode;
190     tif->tif_decodestrip = NeXTDecode;
191     tif->tif_decodetile = NeXTDecode;
192     return (1);
193 }
194 #endif /* NEXT_SUPPORT */
195