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 <stdio.h>
26#include <stdlib.h>
27#include <stdarg.h>
28#include <string.h>
29#include <limits.h>
30
31#include "jbig2.h"
32#include "jbig2_priv.h"
33#include "jbig2_image.h"
34#include "jbig2_page.h"
35#include "jbig2_segment.h"
36
37static void *
38jbig2_default_alloc(Jbig2Allocator *allocator, size_t size)
39{
40 return malloc(size);
41}
42
43static void
44jbig2_default_free(Jbig2Allocator *allocator, void *p)
45{
46 free(p);
47}
48
49static void *
50jbig2_default_realloc(Jbig2Allocator *allocator, void *p, size_t size)
51{
52 return realloc(p, size);
53}
54
55static Jbig2Allocator jbig2_default_allocator = {
56 jbig2_default_alloc,
57 jbig2_default_free,
58 jbig2_default_realloc
59};
60
61void *
62jbig2_alloc(Jbig2Allocator *allocator, size_t size, size_t num)
63{
64 /* Check for integer multiplication overflow when computing
65 the full size of the allocation. */
66 if (num > 0 && size > SIZE_MAX / num)
67 return NULL;
68 return allocator->alloc(allocator, size * num);
69}
70
71/* jbig2_free and jbig2_realloc moved to the bottom of this file */
72
73static void
74jbig2_default_error(void *data, const char *msg, Jbig2Severity severity, int32_t seg_idx)
75{
76 /* report only fatal errors by default */
77 if (severity == JBIG2_SEVERITY_FATAL) {
78 fprintf(stderr, "jbig2 decoder FATAL ERROR: %s", msg);
79 if (seg_idx != -1)
80 fprintf(stderr, " (segment 0x%02x)", seg_idx);
81 fprintf(stderr, "\n");
82 fflush(stderr);
83 }
84}
85
86int
87jbig2_error(Jbig2Ctx *ctx, Jbig2Severity severity, int32_t segment_number, const char *fmt, ...)
88{
89 char buf[1024];
90 va_list ap;
91 int n;
92
93 va_start(ap, fmt);
94 n = vsnprintf(buf, sizeof(buf), fmt, ap);
95 va_end(ap);
96 if (n < 0 || n == sizeof(buf))
97 strncpy(buf, "failed to generate error string", sizeof(buf));
98 ctx->error_callback(ctx->error_callback_data, buf, severity, segment_number);
99 return -1;
100}
101
102Jbig2Ctx *
103jbig2_ctx_new_imp(Jbig2Allocator *allocator, Jbig2Options options, Jbig2GlobalCtx *global_ctx, Jbig2ErrorCallback error_callback, void *error_callback_data, int jbig2_version_major, int jbig2_version_minor)
104{
105 Jbig2Ctx *result;
106
107 if (jbig2_version_major != JBIG2_VERSION_MAJOR || jbig2_version_minor != JBIG2_VERSION_MINOR) {
108 Jbig2Ctx fakectx;
109 fakectx.error_callback = error_callback;
110 fakectx.error_callback_data = error_callback_data;
111 jbig2_error(&fakectx, JBIG2_SEVERITY_FATAL, -1, "incompatible jbig2dec header (%d.%d) and library (%d.%d) versions",
112 jbig2_version_major, jbig2_version_minor, JBIG2_VERSION_MAJOR, JBIG2_VERSION_MINOR);
113 return NULL;
114 }
115
116 if (allocator == NULL)
117 allocator = &jbig2_default_allocator;
118 if (error_callback == NULL)
119 error_callback = &jbig2_default_error;
120
121 result = (Jbig2Ctx *) jbig2_alloc(allocator, sizeof(Jbig2Ctx), 1);
122 if (result == NULL) {
123 error_callback(error_callback_data, "failed to allocate initial context", JBIG2_SEVERITY_FATAL, -1);
124 return NULL;
125 }
126
127 result->allocator = allocator;
128 result->options = options;
129 result->global_ctx = (const Jbig2Ctx *)global_ctx;
130 result->error_callback = error_callback;
131 result->error_callback_data = error_callback_data;
132
133 result->state = (options & JBIG2_OPTIONS_EMBEDDED) ? JBIG2_FILE_SEQUENTIAL_HEADER : JBIG2_FILE_HEADER;
134
135 result->buf = NULL;
136
137 result->n_segments = 0;
138 result->n_segments_max = 16;
139 result->segments = jbig2_new(result, Jbig2Segment *, result->n_segments_max);
140 if (result->segments == NULL) {
141 error_callback(error_callback_data, "failed to allocate initial segments", JBIG2_SEVERITY_FATAL, -1);
142 jbig2_free(allocator, result);
143 return NULL;
144 }
145 result->segment_index = 0;
146
147 result->current_page = 0;
148 result->max_page_index = 4;
149 result->pages = jbig2_new(result, Jbig2Page, result->max_page_index);
150 if (result->pages == NULL) {
151 error_callback(error_callback_data, "failed to allocated initial pages", JBIG2_SEVERITY_FATAL, -1);
152 jbig2_free(allocator, result->segments);
153 jbig2_free(allocator, result);
154 return NULL;
155 }
156 {
157 int index;
158
159 for (index = 0; index < result->max_page_index; index++) {
160 result->pages[index].state = JBIG2_PAGE_FREE;
161 result->pages[index].number = 0;
162 result->pages[index].width = 0;
163 result->pages[index].height = 0xffffffff;
164 result->pages[index].x_resolution = 0;
165 result->pages[index].y_resolution = 0;
166 result->pages[index].stripe_size = 0;
167 result->pages[index].striped = 0;
168 result->pages[index].end_row = 0;
169 result->pages[index].flags = 0;
170 result->pages[index].image = NULL;
171 }
172 }
173
174 return result;
175}
176
177#define get_uint16(bptr)\
178 (((bptr)[0] << 8) | (bptr)[1])
179#define get_int16(bptr)\
180 (((int)get_uint16(bptr) ^ 0x8000) - 0x8000)
181
182int16_t
183jbig2_get_int16(const byte *bptr)
184{
185 return get_int16(bptr);
186}
187
188uint16_t
189jbig2_get_uint16(const byte *bptr)
190{
191 return get_uint16(bptr);
192}
193
194int32_t
195jbig2_get_int32(const byte *bptr)
196{
197 return ((int32_t) get_int16(bptr) << 16) | get_uint16(bptr + 2);
198}
199
200uint32_t
201jbig2_get_uint32(const byte *bptr)
202{
203 return ((uint32_t) get_uint16(bptr) << 16) | get_uint16(bptr + 2);
204}
205
206/**
207 * jbig2_data_in: submit data for decoding
208 * @ctx: The jbig2dec decoder context
209 * @data: a pointer to the data buffer
210 * @size: the size of the data buffer in bytes
211 *
212 * Copies the specified data into internal storage and attempts
213 * to (continue to) parse it as part of a jbig2 data stream.
214 *
215 * Return code: 0 on success
216 * -1 if there is a parsing error
217 **/
218int
219jbig2_data_in(Jbig2Ctx *ctx, const unsigned char *data, size_t size)
220{
221 const size_t initial_buf_size = 1024;
222
223 if (ctx->buf == NULL) {
224 size_t buf_size = initial_buf_size;
225
226 do
227 buf_size <<= 1;
228 while (buf_size < size);
229 ctx->buf = jbig2_new(ctx, byte, buf_size);
230 if (ctx->buf == NULL) {
231 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to allocate buffer when reading data");
232 }
233 ctx->buf_size = buf_size;
234 ctx->buf_rd_ix = 0;
235 ctx->buf_wr_ix = 0;
236 } else if (ctx->buf_wr_ix + size > ctx->buf_size) {
237 if (ctx->buf_rd_ix <= (ctx->buf_size >> 1) && ctx->buf_wr_ix - ctx->buf_rd_ix + size <= ctx->buf_size) {
238 memmove(ctx->buf, ctx->buf + ctx->buf_rd_ix, ctx->buf_wr_ix - ctx->buf_rd_ix);
239 } else {
240 byte *buf;
241 size_t buf_size = initial_buf_size;
242
243 do
244 buf_size <<= 1;
245 while (buf_size < ctx->buf_wr_ix - ctx->buf_rd_ix + size);
246 buf = jbig2_new(ctx, byte, buf_size);
247 if (buf == NULL) {
248 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to allocate bigger buffer when reading data");
249 }
250 memcpy(buf, ctx->buf + ctx->buf_rd_ix, ctx->buf_wr_ix - ctx->buf_rd_ix);
251 jbig2_free(ctx->allocator, ctx->buf);
252 ctx->buf = buf;
253 ctx->buf_size = buf_size;
254 }
255 ctx->buf_wr_ix -= ctx->buf_rd_ix;
256 ctx->buf_rd_ix = 0;
257 }
258 memcpy(ctx->buf + ctx->buf_wr_ix, data, size);
259 ctx->buf_wr_ix += size;
260
261 /* data has now been added to buffer */
262
263 for (;;) {
264 const byte jbig2_id_string[8] = { 0x97, 0x4a, 0x42, 0x32, 0x0d, 0x0a, 0x1a, 0x0a };
265 Jbig2Segment *segment;
266 size_t header_size;
267 int code;
268
269 switch (ctx->state) {
270 case JBIG2_FILE_HEADER:
271 /* D.4.1 */
272 if (ctx->buf_wr_ix - ctx->buf_rd_ix < 9)
273 return 0;
274 if (memcmp(ctx->buf + ctx->buf_rd_ix, jbig2_id_string, 8))
275 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "not a JBIG2 file header");
276 /* D.4.2 */
277 ctx->file_header_flags = ctx->buf[ctx->buf_rd_ix + 8];
278 /* Check for T.88 amendment 2 */
279 if (ctx->file_header_flags & 0x04)
280 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "file header indicates use of 12 adaptive template pixels (NYI)");
281 /* Check for T.88 amendment 3 */
282 if (ctx->file_header_flags & 0x08)
283 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "file header indicates use of colored region segments (NYI)");
284 if (ctx->file_header_flags & 0xFC) {
285 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "reserved bits (2-7) of file header flags are not zero (0x%02x)", ctx->file_header_flags);
286 }
287 /* D.4.3 */
288 if (!(ctx->file_header_flags & 2)) { /* number of pages is known */
289 if (ctx->buf_wr_ix - ctx->buf_rd_ix < 13)
290 return 0;
291 ctx->n_pages = jbig2_get_uint32(ctx->buf + ctx->buf_rd_ix + 9);
292 ctx->buf_rd_ix += 13;
293 if (ctx->n_pages == 1)
294 jbig2_error(ctx, JBIG2_SEVERITY_INFO, -1, "file header indicates a single page document");
295 else
296 jbig2_error(ctx, JBIG2_SEVERITY_INFO, -1, "file header indicates a %d page document", ctx->n_pages);
297 } else { /* number of pages not known */
298 ctx->n_pages = 0;
299 ctx->buf_rd_ix += 9;
300 }
301 /* determine the file organization based on the flags - D.4.2 again */
302 if (ctx->file_header_flags & 1) {
303 ctx->state = JBIG2_FILE_SEQUENTIAL_HEADER;
304 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1, "file header indicates sequential organization");
305 } else {
306 ctx->state = JBIG2_FILE_RANDOM_HEADERS;
307 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1, "file header indicates random-access organization");
308 }
309 break;
310 case JBIG2_FILE_SEQUENTIAL_HEADER:
311 case JBIG2_FILE_RANDOM_HEADERS:
312 segment = jbig2_parse_segment_header(ctx, ctx->buf + ctx->buf_rd_ix, ctx->buf_wr_ix - ctx->buf_rd_ix, &header_size);
313 if (segment == NULL)
314 return 0; /* need more data */
315 ctx->buf_rd_ix += header_size;
316
317 if (ctx->n_segments == ctx->n_segments_max) {
318 Jbig2Segment **segments;
319
320 segments = jbig2_renew(ctx, ctx->segments, Jbig2Segment *, (ctx->n_segments_max <<= 2));
321 if (segments == NULL) {
322 ctx->state = JBIG2_FILE_EOF;
323 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate space for more segments");
324 }
325 ctx->segments = segments;
326 }
327
328
329 ctx->segments[ctx->n_segments++] = segment;
330 if (ctx->state == JBIG2_FILE_RANDOM_HEADERS) {
331 if ((segment->flags & 63) == 51) /* end of file */
332 ctx->state = JBIG2_FILE_RANDOM_BODIES;
333 } else /* JBIG2_FILE_SEQUENTIAL_HEADER */
334 ctx->state = JBIG2_FILE_SEQUENTIAL_BODY;
335 break;
336 case JBIG2_FILE_SEQUENTIAL_BODY:
337 case JBIG2_FILE_RANDOM_BODIES:
338 segment = ctx->segments[ctx->segment_index];
339
340 /* immediate generic regions may have unknown size */
341 if (segment->data_length == 0xffffffff && (segment->flags & 63) == 38) {
342 byte *s, *e, *p;
343 int mmr;
344 byte mmr_marker[2] = { 0x00, 0x00 };
345 byte arith_marker[2] = { 0xff, 0xac };
346 byte *desired_marker;
347
348 s = p = ctx->buf + ctx->buf_rd_ix;
349 e = ctx->buf + ctx->buf_wr_ix;
350
351 if (e - p < 18)
352 return 0; /* need more data */
353
354 mmr = p[17] & 1;
355 p += 18;
356 desired_marker = mmr ? mmr_marker : arith_marker;
357
358 /* look for two byte marker */
359 if (e - p < 2)
360 return 0; /* need more data */
361
362 while (p[0] != desired_marker[0] || p[1] != desired_marker[1]) {
363 p++;
364 if (e - p < 2)
365 return 0; /* need more data */
366 }
367 p += 2;
368
369 /* the marker is followed by a four byte row count */
370 if (e - p < 4)
371 return 0; /* need more data */
372 segment->rows = jbig2_get_uint32(p);
373 p += 4;
374
375 segment->data_length = p - s;
376 jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "unknown length determined to be %u", segment->data_length);
377 }
378 else if (segment->data_length > ctx->buf_wr_ix - ctx->buf_rd_ix)
379 return 0; /* need more data */
380
381 code = jbig2_parse_segment(ctx, segment, ctx->buf + ctx->buf_rd_ix);
382 ctx->buf_rd_ix += segment->data_length;
383 ctx->segment_index++;
384 if (ctx->state == JBIG2_FILE_RANDOM_BODIES) {
385 if (ctx->segment_index == ctx->n_segments)
386 ctx->state = JBIG2_FILE_EOF;
387 } else { /* JBIG2_FILE_SEQUENCIAL_BODY */
388 ctx->state = JBIG2_FILE_SEQUENTIAL_HEADER;
389 }
390 if (code < 0) {
391 ctx->state = JBIG2_FILE_EOF;
392 return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode; treating as end of file");
393 }
394 break;
395 case JBIG2_FILE_EOF:
396 if (ctx->buf_rd_ix == ctx->buf_wr_ix)
397 return 0;
398 return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "garbage beyond end of file");
399 }
400 }
401}
402
403Jbig2Allocator *
404jbig2_ctx_free(Jbig2Ctx *ctx)
405{
406 Jbig2Allocator *ca;
407 int i;
408
409 if (ctx == NULL)
410 return NULL;
411
412 ca = ctx->allocator;
413 jbig2_free(ca, ctx->buf);
414 if (ctx->segments != NULL) {
415 for (i = 0; i < ctx->n_segments; i++)
416 jbig2_free_segment(ctx, ctx->segments[i]);
417 jbig2_free(ca, ctx->segments);
418 }
419
420 if (ctx->pages != NULL) {
421 for (i = 0; i <= ctx->current_page; i++)
422 if (ctx->pages[i].image != NULL)
423 jbig2_image_release(ctx, ctx->pages[i].image);
424 jbig2_free(ca, ctx->pages);
425 }
426
427 jbig2_free(ca, ctx);
428
429 return ca;
430}
431
432Jbig2GlobalCtx *
433jbig2_make_global_ctx(Jbig2Ctx *ctx)
434{
435 return (Jbig2GlobalCtx *) ctx;
436}
437
438Jbig2Allocator *
439jbig2_global_ctx_free(Jbig2GlobalCtx *global_ctx)
440{
441 return jbig2_ctx_free((Jbig2Ctx *) global_ctx);
442}
443
444/* I'm not committed to keeping the word stream interface. It's handy
445 when you think you may be streaming your input, but if you're not
446 (as is currently the case), it just adds complexity.
447*/
448
449typedef struct {
450 Jbig2WordStream super;
451 const byte *data;
452 size_t size;
453} Jbig2WordStreamBuf;
454
455static int
456jbig2_word_stream_buf_get_next_word(Jbig2WordStream *self, size_t offset, uint32_t *word)
457{
458 Jbig2WordStreamBuf *z = (Jbig2WordStreamBuf *) self;
459 uint32_t val = 0;
460 int ret = 0;
461
462 if (self == NULL || word == NULL)
463 return -1;
464 if (offset >= z->size) {
465 *word = 0;
466 return 0;
467 }
468
469 if (offset < z->size) {
470 val |= z->data[offset] << 24;
471 ret++;
472 }
473 if (offset + 1 < z->size) {
474 val |= z->data[offset + 1] << 16;
475 ret++;
476 }
477 if (offset + 2 < z->size) {
478 val |= z->data[offset + 2] << 8;
479 ret++;
480 }
481 if (offset + 3 < z->size) {
482 val |= z->data[offset + 3];
483 ret++;
484 }
485 *word = val;
486 return ret;
487}
488
489Jbig2WordStream *
490jbig2_word_stream_buf_new(Jbig2Ctx *ctx, const byte *data, size_t size)
491{
492 Jbig2WordStreamBuf *result = jbig2_new(ctx, Jbig2WordStreamBuf, 1);
493
494 if (result == NULL) {
495 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to allocate word stream");
496 return NULL;
497 }
498
499 result->super.get_next_word = jbig2_word_stream_buf_get_next_word;
500 result->data = data;
501 result->size = size;
502
503 return &result->super;
504}
505
506void
507jbig2_word_stream_buf_free(Jbig2Ctx *ctx, Jbig2WordStream *ws)
508{
509 jbig2_free(ctx->allocator, ws);
510}
511
512/* When Memento is in use, the ->free and ->realloc calls get
513 * turned into ->Memento_free and ->Memento_realloc, which is
514 * obviously problematic. Undefine free and realloc here to
515 * avoid this. */
516#ifdef MEMENTO
517#undef free
518#undef realloc
519#endif
520
521void
522jbig2_free(Jbig2Allocator *allocator, void *p)
523{
524 allocator->free(allocator, p);
525}
526
527void *
528jbig2_realloc(Jbig2Allocator *allocator, void *p, size_t size, size_t num)
529{
530 /* check for integer multiplication overflow */
531 if (num > 0 && size >= SIZE_MAX / num)
532 return NULL;
533 return allocator->realloc(allocator, p, size * num);
534}
535