Coverage Report

Created: 2025-11-16 07:40

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