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