1/* Copyright (C) 2001-2019 Artifex Software, Inc.
2 All Rights Reserved.
3
4 This software is provided AS-IS with no warranty, either express or
5 implied.
6
7 This software is distributed under license and may not be copied,
8 modified or distributed except as expressly authorized under the terms
9 of the license contained in the file LICENSE in this distribution.
10
11 Refer to licensing information at http://www.artifex.com or contact
12 Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato,
13 CA 94945, U.S.A., +1(415)492-9861, for further information.
14*/
15
16/*
17 jbig2dec
18*/
19
20#ifdef HAVE_CONFIG_H
21#include "config.h"
22#endif
23#include "os_types.h"
24
25#include <stddef.h> /* size_t */
26
27#include "jbig2.h"
28#include "jbig2_priv.h"
29#include "jbig2_arith.h"
30#include "jbig2_arith_int.h"
31#include "jbig2_arith_iaid.h"
32#include "jbig2_generic.h"
33#include "jbig2_image.h"
34#include "jbig2_halftone.h"
35#include "jbig2_huffman.h"
36#include "jbig2_page.h"
37#include "jbig2_refinement.h"
38#include "jbig2_segment.h"
39#include "jbig2_symbol_dict.h"
40#include "jbig2_text.h"
41
42#if !defined (UINT32_MAX)
43#define UINT32_MAX 0xffffffff
44#endif
45
46Jbig2Segment *
47jbig2_parse_segment_header(Jbig2Ctx *ctx, uint8_t *buf, size_t buf_size, size_t *p_header_size)
48{
49 Jbig2Segment *result;
50 uint8_t rtscarf;
51 uint32_t rtscarf_long;
52 uint32_t *referred_to_segments;
53 uint32_t referred_to_segment_count;
54 uint32_t referred_to_segment_size;
55 uint32_t pa_size;
56 uint32_t offset;
57
58 /* minimum possible size of a jbig2 segment header */
59 if (buf_size < 11)
60 return NULL;
61
62 result = jbig2_new(ctx, Jbig2Segment, 1);
63 if (result == NULL) {
64 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to allocate segment");
65 return NULL;
66 }
67
68 /* 7.2.2 */
69 result->number = jbig2_get_uint32(buf);
70
71 /* 7.2.3 */
72 result->flags = buf[4];
73
74 /* 7.2.4 referred-to segments */
75 rtscarf = buf[5];
76 if ((rtscarf & 0xe0) == 0xe0) {
77 rtscarf_long = jbig2_get_uint32(buf + 5);
78 referred_to_segment_count = rtscarf_long & 0x1fffffff;
79 offset = 5 + 4 + (referred_to_segment_count + 1) / 8;
80 } else {
81 referred_to_segment_count = (rtscarf >> 5);
82 offset = 5 + 1;
83 }
84 result->referred_to_segment_count = referred_to_segment_count;
85
86 /* we now have enough information to compute the full header length */
87 referred_to_segment_size = result->number <= 256 ? 1 : result->number <= 65536 ? 2 : 4; /* 7.2.5 */
88 pa_size = result->flags & 0x40 ? 4 : 1; /* 7.2.6 */
89 if (offset + referred_to_segment_count * referred_to_segment_size + pa_size + 4 > buf_size) {
90 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, result->number, "insufficient data to parse segment header", -1);
91 jbig2_free(ctx->allocator, result);
92 return NULL;
93 }
94
95 /* 7.2.5 */
96 if (referred_to_segment_count) {
97 uint32_t i;
98
99 referred_to_segments = jbig2_new(ctx, uint32_t, referred_to_segment_count * referred_to_segment_size);
100 if (referred_to_segments == NULL) {
101 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, result->number, "failed to allocate referred to segments");
102 return NULL;
103 }
104
105 for (i = 0; i < referred_to_segment_count; i++) {
106 referred_to_segments[i] =
107 (referred_to_segment_size == 1) ? buf[offset] :
108 (referred_to_segment_size == 2) ? jbig2_get_uint16(buf + offset) : jbig2_get_uint32(buf + offset);
109 offset += referred_to_segment_size;
110 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, result->number, "segment %d refers to segment %d", result->number, referred_to_segments[i]);
111 }
112 result->referred_to_segments = referred_to_segments;
113 } else { /* no referred-to segments */
114
115 result->referred_to_segments = NULL;
116 }
117
118 /* 7.2.6 */
119 if (pa_size == 4) {
120 result->page_association = jbig2_get_uint32(buf + offset);
121 offset += 4;
122 } else {
123 result->page_association = buf[offset++];
124 }
125 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, result->number, "segment %d is associated with page %d", result->number, result->page_association);
126
127 /* 7.2.7 */
128 result->rows = UINT32_MAX;
129 result->data_length = jbig2_get_uint32(buf + offset);
130 *p_header_size = offset + 4;
131
132 /* no body parsing results yet */
133 result->result = NULL;
134
135 return result;
136}
137
138void
139jbig2_free_segment(Jbig2Ctx *ctx, Jbig2Segment *segment)
140{
141 if (segment == NULL)
142 return;
143
144 jbig2_free(ctx->allocator, segment->referred_to_segments);
145 /* todo: we need either some separate fields or
146 a more complex result object rather than this
147 brittle special casing */
148 switch (segment->flags & 63) {
149 case 0: /* symbol dictionary */
150 if (segment->result != NULL)
151 jbig2_sd_release(ctx, (Jbig2SymbolDict *) segment->result);
152 break;
153 case 4: /* intermediate text region */
154 case 40: /* intermediate refinement region */
155 if (segment->result != NULL)
156 jbig2_image_release(ctx, (Jbig2Image *) segment->result);
157 break;
158 case 16: /* pattern dictionary */
159 if (segment->result != NULL)
160 jbig2_hd_release(ctx, (Jbig2PatternDict *) segment->result);
161 break;
162 case 53: /* user-supplied huffman table */
163 if (segment->result != NULL)
164 jbig2_table_free(ctx, (Jbig2HuffmanParams *) segment->result);
165 break;
166 default:
167 /* anything else is probably an undefined pointer */
168 break;
169 }
170 jbig2_free(ctx->allocator, segment);
171}
172
173/* find a segment by number */
174Jbig2Segment *
175jbig2_find_segment(Jbig2Ctx *ctx, uint32_t number)
176{
177 int index, index_max = ctx->segment_index - 1;
178 const Jbig2Ctx *global_ctx = ctx->global_ctx;
179
180 /* FIXME: binary search would be better */
181 for (index = index_max; index >= 0; index--)
182 if (ctx->segments[index]->number == number)
183 return (ctx->segments[index]);
184
185 if (global_ctx)
186 for (index = global_ctx->segment_index - 1; index >= 0; index--)
187 if (global_ctx->segments[index]->number == number)
188 return (global_ctx->segments[index]);
189
190 /* didn't find a match */
191 return NULL;
192}
193
194/* parse the generic portion of a region segment data header */
195void
196jbig2_get_region_segment_info(Jbig2RegionSegmentInfo *info, const uint8_t *segment_data)
197{
198 /* 7.4.1 */
199 info->width = jbig2_get_uint32(segment_data);
200 info->height = jbig2_get_uint32(segment_data + 4);
201 info->x = jbig2_get_uint32(segment_data + 8);
202 info->y = jbig2_get_uint32(segment_data + 12);
203 info->flags = segment_data[16];
204 info->op = (Jbig2ComposeOp)(info->flags & 0x7);
205}
206
207/* dispatch code for extension segment parsing */
208static int
209jbig2_parse_extension_segment(Jbig2Ctx *ctx, Jbig2Segment *segment, const uint8_t *segment_data)
210{
211 uint32_t type;
212 bool reserved;
213 bool necessary;
214
215 if (segment->data_length < 4)
216 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short");
217
218 type = jbig2_get_uint32(segment_data);
219 reserved = type & 0x20000000;
220 /* Not implemented since this bit
221 is only needed by encoders.
222 dependent = type & 0x40000000;
223 */
224 necessary = type & 0x80000000;
225
226 if (necessary && !reserved) {
227 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "extension segment is marked 'necessary' but not 'reserved' contrary to spec");
228 }
229
230 switch (type) {
231 case 0x20000000:
232 jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "ignoring ASCII comment");
233 break;
234 case 0x20000002:
235 jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "ignoring UCS-2 comment");
236 break;
237 default:
238 if (necessary) {
239 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "unhandled necessary extension segment type 0x%08x", type);
240 } else {
241 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unhandled non-necessary extension segment, skipping");
242 }
243 }
244
245 return 0;
246}
247
248/* dispatch code for profile segment parsing */
249static int
250jbig2_parse_profile_segment(Jbig2Ctx *ctx, Jbig2Segment *segment, const uint8_t *segment_data)
251{
252 uint32_t profiles;
253 uint32_t i;
254 uint32_t profile;
255 int index;
256 const char *requirements;
257 const char *generic_region;
258 const char *refinement_region;
259 const char *halftone_region;
260 const char *numerical_data;
261
262 if (segment->data_length < 4)
263 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "Segment too short");
264 index = 0;
265
266 profiles = jbig2_get_uint32(&segment_data[index]);
267 index += 4;
268
269 for (i = 0; i < profiles; i++) {
270 if (segment->data_length - index < 4)
271 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short to store profile");
272
273 profile = jbig2_get_uint32(&segment_data[index]);
274 index += 4;
275
276 switch (profile) {
277 case 0x00000001:
278 requirements = "All JBIG2 capabilities";
279 generic_region = "No restriction";
280 refinement_region = "No restriction";
281 halftone_region = "No restriction";
282 numerical_data = "No restriction";
283 break;
284 case 0x00000002:
285 requirements = "Maximum compression";
286 generic_region = "Arithmetic only; any template used";
287 refinement_region = "No restriction";
288 halftone_region = "No restriction";
289 numerical_data = "Arithmetic only";
290 break;
291 case 0x00000003:
292 requirements = "Medium complexity and medium compression";
293 generic_region = "Arithmetic only; only 10-pixel and 13-pixel templates";
294 refinement_region = "10-pixel template only";
295 halftone_region = "No skip mask used";
296 numerical_data = "Arithmetic only";
297 break;
298 case 0x00000004:
299 requirements = "Low complexity with progressive lossless capability";
300 generic_region = "MMR only";
301 refinement_region = "10-pixel template only";
302 halftone_region = "No skip mask used";
303 numerical_data = "Huffman only";
304 break;
305 case 0x00000005:
306 requirements = "Low complexity";
307 generic_region = "MMR only";
308 refinement_region = "Not available";
309 halftone_region = "No skip mask used";
310 numerical_data = "Huffman only";
311 break;
312 default:
313 requirements = "Unknown";
314 generic_region = "Unknown";
315 refinement_region = "Unknown";
316 halftone_region = "Unknown";
317 numerical_data = "Unknown";
318 break;
319 }
320
321 jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "Supported profile: 0x%08x", profile);
322 jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, " Requirements: %s", requirements);
323 jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, " Generic region coding: %s", generic_region);
324 jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, " Refinement region coding: %s", refinement_region);
325 jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, " Halftone region coding: %s", halftone_region);
326 jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, " Numerical data: %s", numerical_data);
327 }
328
329 return 0;
330}
331
332/* general segment parsing dispatch */
333int
334jbig2_parse_segment(Jbig2Ctx *ctx, Jbig2Segment *segment, const uint8_t *segment_data)
335{
336 jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
337 "segment %d, flags=%x, type=%d, data_length=%d", segment->number, segment->flags, segment->flags & 63, segment->data_length);
338 switch (segment->flags & 63) {
339 case 0:
340 return jbig2_symbol_dictionary(ctx, segment, segment_data);
341 case 4: /* intermediate text region */
342 case 6: /* immediate text region */
343 case 7: /* immediate lossless text region */
344 return jbig2_text_region(ctx, segment, segment_data);
345 case 16:
346 return jbig2_pattern_dictionary(ctx, segment, segment_data);
347 case 20: /* intermediate halftone region */
348 case 22: /* immediate halftone region */
349 case 23: /* immediate lossless halftone region */
350 return jbig2_halftone_region(ctx, segment, segment_data);
351 case 36:
352 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "unhandled segment type 'intermediate generic region' (NYI)");
353 case 38: /* immediate generic region */
354 case 39: /* immediate lossless generic region */
355 return jbig2_immediate_generic_region(ctx, segment, segment_data);
356 case 40: /* intermediate generic refinement region */
357 case 42: /* immediate generic refinement region */
358 case 43: /* immediate lossless generic refinement region */
359 return jbig2_refinement_region(ctx, segment, segment_data);
360 case 48:
361 return jbig2_page_info(ctx, segment, segment_data);
362 case 49:
363 return jbig2_end_of_page(ctx, segment, segment_data);
364 case 50:
365 return jbig2_end_of_stripe(ctx, segment, segment_data);
366 case 51:
367 ctx->state = JBIG2_FILE_EOF;
368 jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "end of file");
369 break;
370 case 52:
371 return jbig2_parse_profile_segment(ctx, segment, segment_data);
372 case 53: /* user-supplied huffman table */
373 return jbig2_table(ctx, segment, segment_data);
374 case 54:
375 return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unhandled segment type 'color palette' (NYI)");
376 case 62:
377 return jbig2_parse_extension_segment(ctx, segment, segment_data);
378 default:
379 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unknown segment type %d", segment->flags & 63);
380 }
381 return 0;
382}
383