Coverage Report

Created: 2026-07-24 07:44

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