Coverage Report

Created: 2025-12-11 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/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
22.8M
{
64
    /* Check for integer multiplication overflow when computing
65
    the full size of the allocation. */
66
22.8M
    if (num > 0 && size > SIZE_MAX / num)
67
0
        return NULL;
68
22.8M
    return allocator->alloc(allocator, size * num);
69
22.8M
}
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
38.2M
{
76
    /* report only fatal errors by default */
77
38.2M
    if (severity == JBIG2_SEVERITY_FATAL) {
78
2.58k
        fprintf(stderr, "jbig2 decoder FATAL ERROR: %s", msg);
79
2.58k
        if (seg_idx != JBIG2_UNKNOWN_SEGMENT_NUMBER)
80
881
            fprintf(stderr, " (segment 0x%02x)", seg_idx);
81
2.58k
        fprintf(stderr, "\n");
82
2.58k
        fflush(stderr);
83
2.58k
    }
84
38.2M
}
85
86
int
87
jbig2_error(Jbig2Ctx *ctx, Jbig2Severity severity, uint32_t segment_number, const char *fmt, ...)
88
38.2M
{
89
38.2M
    char buf[1024];
90
38.2M
    va_list ap;
91
38.2M
    int n;
92
93
38.2M
    va_start(ap, fmt);
94
38.2M
    n = vsnprintf(buf, sizeof(buf), fmt, ap);
95
38.2M
    va_end(ap);
96
38.2M
    if (n < 0 || n == sizeof(buf))
97
0
        strncpy(buf, "failed to generate error string", sizeof(buf));
98
38.2M
    ctx->error_callback(ctx->error_callback_data, buf, severity, segment_number);
99
38.2M
    return -1;
100
38.2M
}
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
2.96k
{
105
2.96k
    Jbig2Ctx *result;
106
107
2.96k
    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
2.96k
    if (allocator == NULL)
117
0
        allocator = &jbig2_default_allocator;
118
2.96k
    if (error_callback == NULL)
119
2.96k
        error_callback = &jbig2_default_error;
120
121
2.96k
    result = (Jbig2Ctx *) jbig2_alloc(allocator, sizeof(Jbig2Ctx), 1);
122
2.96k
    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
2.96k
    result->allocator = allocator;
128
2.96k
    result->options = options;
129
2.96k
    result->global_ctx = (const Jbig2Ctx *)global_ctx;
130
2.96k
    result->error_callback = error_callback;
131
2.96k
    result->error_callback_data = error_callback_data;
132
133
2.96k
    result->state = (options & JBIG2_OPTIONS_EMBEDDED) ? JBIG2_FILE_SEQUENTIAL_HEADER : JBIG2_FILE_HEADER;
134
135
2.96k
    result->buf = NULL;
136
137
2.96k
    result->n_segments = 0;
138
2.96k
    result->n_segments_max = 16;
139
2.96k
    result->segments = jbig2_new(result, Jbig2Segment *, result->n_segments_max);
140
2.96k
    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
2.96k
    result->segment_index = 0;
146
147
2.96k
    result->current_page = 0;
148
2.96k
    result->max_page_index = 4;
149
2.96k
    result->pages = jbig2_new(result, Jbig2Page, result->max_page_index);
150
2.96k
    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
2.96k
    {
157
2.96k
        uint32_t index;
158
159
14.8k
        for (index = 0; index < result->max_page_index; index++) {
160
11.8k
            result->pages[index].state = JBIG2_PAGE_FREE;
161
11.8k
            result->pages[index].number = 0;
162
11.8k
            result->pages[index].width = 0;
163
11.8k
            result->pages[index].height = 0xffffffff;
164
11.8k
            result->pages[index].x_resolution = 0;
165
11.8k
            result->pages[index].y_resolution = 0;
166
11.8k
            result->pages[index].stripe_size = 0;
167
11.8k
            result->pages[index].striped = 0;
168
11.8k
            result->pages[index].end_row = 0;
169
11.8k
            result->pages[index].flags = 0;
170
11.8k
            result->pages[index].image = NULL;
171
11.8k
        }
172
2.96k
    }
173
174
2.96k
    return result;
175
2.96k
}
176
177
#define get_uint16(bptr)\
178
379k
    (((bptr)[0] << 8) | (bptr)[1])
179
#define get_int16(bptr)\
180
7.97k
    (((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
3.09k
{
187
3.09k
    return get_int16(bptr);
188
3.09k
}
189
190
/* coverity[ -tainted_data_return ] */
191
/* coverity[ -tainted_data_argument : arg-0 ] */
192
uint16_t
193
jbig2_get_uint16(const byte *bptr)
194
10.4k
{
195
10.4k
    return get_uint16(bptr);
196
10.4k
}
197
198
/* coverity[ -tainted_data_return ] */
199
/* coverity[ -tainted_data_argument : arg-0 ] */
200
int32_t
201
jbig2_get_int32(const byte *bptr)
202
4.88k
{
203
4.88k
    return ((int32_t) get_int16(bptr) << 16) | get_uint16(bptr + 2);
204
4.88k
}
205
206
/* coverity[ -tainted_data_return ] */
207
/* coverity[ -tainted_data_argument : arg-0 ] */
208
uint32_t
209
jbig2_get_uint32(const byte *bptr)
210
178k
{
211
178k
    return ((uint32_t) get_uint16(bptr) << 16) | get_uint16(bptr + 2);
212
178k
}
213
214
static size_t
215
jbig2_find_buffer_size(size_t desired)
216
2.96k
{
217
2.96k
    const size_t initial_buf_size = 1024;
218
2.96k
    size_t size = initial_buf_size;
219
220
2.96k
    if (desired == SIZE_MAX)
221
0
        return SIZE_MAX;
222
223
4.34k
    while (size < desired)
224
1.38k
        size <<= 1;
225
226
2.96k
    return size;
227
2.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
2.96k
{
245
2.96k
    if (ctx->buf == NULL) {
246
2.96k
        size_t buf_size = jbig2_find_buffer_size(size);
247
2.96k
        ctx->buf = jbig2_new(ctx, byte, buf_size);
248
2.96k
        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
2.96k
        ctx->buf_size = buf_size;
252
2.96k
        ctx->buf_rd_ix = 0;
253
2.96k
        ctx->buf_wr_ix = 0;
254
2.96k
    } else if (size > ctx->buf_size - ctx->buf_wr_ix) {
255
0
        size_t already = ctx->buf_wr_ix - ctx->buf_rd_ix;
256
257
0
        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
0
        } else {
260
0
            byte *buf;
261
0
            size_t buf_size;
262
263
0
            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
0
            buf_size = jbig2_find_buffer_size(size + already);
268
269
0
            buf = jbig2_new(ctx, byte, buf_size);
270
0
            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
0
            memcpy(buf, ctx->buf + ctx->buf_rd_ix, already);
274
0
            jbig2_free(ctx->allocator, ctx->buf);
275
0
            ctx->buf = buf;
276
0
            ctx->buf_size = buf_size;
277
0
        }
278
0
        ctx->buf_wr_ix -= ctx->buf_rd_ix;
279
0
        ctx->buf_rd_ix = 0;
280
0
    }
281
282
2.96k
    memcpy(ctx->buf + ctx->buf_wr_ix, data, size);
283
2.96k
    ctx->buf_wr_ix += size;
284
285
    /* data has now been added to buffer */
286
287
64.6k
    for (;;) {
288
64.6k
        const byte jbig2_id_string[8] = { 0x97, 0x4a, 0x42, 0x32, 0x0d, 0x0a, 0x1a, 0x0a };
289
64.6k
        Jbig2Segment *segment;
290
64.6k
        size_t header_size;
291
64.6k
        int code;
292
293
64.6k
        switch (ctx->state) {
294
2.96k
        case JBIG2_FILE_HEADER:
295
            /* D.4.1 */
296
2.96k
            if (ctx->buf_wr_ix - ctx->buf_rd_ix < 9)
297
3
                return 0;
298
2.96k
            if (memcmp(ctx->buf + ctx->buf_rd_ix, jbig2_id_string, 8))
299
22
                return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "not a JBIG2 file header");
300
            /* D.4.2 */
301
2.93k
            ctx->file_header_flags = ctx->buf[ctx->buf_rd_ix + 8];
302
            /* Check for T.88 amendment 2 */
303
2.93k
            if (ctx->file_header_flags & 0x04)
304
1
                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
2.93k
            if (ctx->file_header_flags & 0x08)
307
1
                return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "file header indicates use of colored region segments (NYI)");
308
2.93k
            if (ctx->file_header_flags & 0xFC) {
309
566
                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
566
            }
311
            /* D.4.3 */
312
2.93k
            if (!(ctx->file_header_flags & 2)) {        /* number of pages is known */
313
1.10k
                if (ctx->buf_wr_ix - ctx->buf_rd_ix < 13)
314
4
                    return 0;
315
1.09k
                ctx->n_pages = jbig2_get_uint32(ctx->buf + ctx->buf_rd_ix + 9);
316
1.09k
                ctx->buf_rd_ix += 13;
317
1.09k
                if (ctx->n_pages == 1)
318
62
                    jbig2_error(ctx, JBIG2_SEVERITY_INFO, JBIG2_UNKNOWN_SEGMENT_NUMBER, "file header indicates a single page document");
319
1.03k
                else
320
1.03k
                    jbig2_error(ctx, JBIG2_SEVERITY_INFO, JBIG2_UNKNOWN_SEGMENT_NUMBER, "file header indicates a %d page document", ctx->n_pages);
321
1.83k
            } else {            /* number of pages not known */
322
1.83k
                ctx->n_pages = 0;
323
1.83k
                ctx->buf_rd_ix += 9;
324
1.83k
            }
325
            /* determine the file organization based on the flags - D.4.2 again */
326
2.93k
            if (ctx->file_header_flags & 1) {
327
2.51k
                ctx->state = JBIG2_FILE_SEQUENTIAL_HEADER;
328
2.51k
                jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, JBIG2_UNKNOWN_SEGMENT_NUMBER, "file header indicates sequential organization");
329
2.51k
            } else {
330
420
                ctx->state = JBIG2_FILE_RANDOM_HEADERS;
331
420
                jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, JBIG2_UNKNOWN_SEGMENT_NUMBER, "file header indicates random-access organization");
332
420
            }
333
2.93k
            break;
334
27.8k
        case JBIG2_FILE_SEQUENTIAL_HEADER:
335
33.6k
        case JBIG2_FILE_RANDOM_HEADERS:
336
33.6k
            segment = jbig2_parse_segment_header(ctx, ctx->buf + ctx->buf_rd_ix, ctx->buf_wr_ix - ctx->buf_rd_ix, &header_size);
337
33.6k
            if (segment == NULL)
338
584
                return 0; /* need more data */
339
33.0k
            ctx->buf_rd_ix += header_size;
340
341
33.0k
            if (ctx->n_segments >= ctx->n_segments_max) {
342
392
                Jbig2Segment **segments;
343
344
392
                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
392
                else if (ctx->n_segments_max > (UINT32_MAX >> 2)) {
350
0
                    ctx->n_segments_max = UINT32_MAX;
351
392
                } else {
352
392
                    ctx->n_segments_max <<= 2;
353
392
                }
354
355
392
                segments = jbig2_renew(ctx, ctx->segments, Jbig2Segment *, ctx->n_segments_max);
356
392
                if (segments == NULL) {
357
2
                    ctx->state = JBIG2_FILE_EOF;
358
2
                    jbig2_free_segment(ctx, segment);
359
2
                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate space for more segments");
360
2
                }
361
390
                ctx->segments = segments;
362
390
            }
363
364
33.0k
            ctx->segments[ctx->n_segments++] = segment;
365
33.0k
            if (ctx->state == JBIG2_FILE_RANDOM_HEADERS) {
366
5.42k
                if ((segment->flags & 63) == 51)        /* end of file */
367
57
                    ctx->state = JBIG2_FILE_RANDOM_BODIES;
368
5.42k
            } else              /* JBIG2_FILE_SEQUENTIAL_HEADER */
369
27.6k
                ctx->state = JBIG2_FILE_SEQUENTIAL_BODY;
370
33.0k
            break;
371
27.6k
        case JBIG2_FILE_SEQUENTIAL_BODY:
372
28.0k
        case JBIG2_FILE_RANDOM_BODIES:
373
28.0k
            segment = ctx->segments[ctx->segment_index];
374
375
            /* immediate generic regions may have unknown size */
376
28.0k
            if (segment->data_length == 0xffffffff && (segment->flags & 63) == 38) {
377
8.52k
                byte *s, *e, *p;
378
8.52k
                int mmr;
379
8.52k
                byte mmr_marker[2] = { 0x00, 0x00 };
380
8.52k
                byte arith_marker[2] = { 0xff, 0xac };
381
8.52k
                byte *desired_marker;
382
383
8.52k
                s = p = ctx->buf + ctx->buf_rd_ix;
384
8.52k
                e = ctx->buf + ctx->buf_wr_ix;
385
386
8.52k
                if (e - p < 18)
387
20
                        return 0; /* need more data */
388
389
8.50k
                mmr = p[17] & 1;
390
8.50k
                p += 18;
391
8.50k
                desired_marker = mmr ? mmr_marker : arith_marker;
392
393
                /* look for two byte marker */
394
8.50k
                if (e - p < 2)
395
23
                    return 0; /* need more data */
396
397
1.24M
                while (p[0] != desired_marker[0] || p[1] != desired_marker[1]) {
398
1.23M
                    p++;
399
1.23M
                    if (e - p < 2)
400
173
                        return 0; /* need more data */
401
1.23M
                }
402
8.31k
                p += 2;
403
404
                /* the marker is followed by a four byte row count */
405
8.31k
                if (e - p < 4)
406
8
                        return 0; /* need more data */
407
8.30k
                segment->rows = jbig2_get_uint32(p);
408
8.30k
                p += 4;
409
410
8.30k
                segment->data_length = (size_t) (p - s);
411
8.30k
                jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "unknown length determined to be %lu", (long) segment->data_length);
412
8.30k
            }
413
19.5k
            else if (segment->data_length > ctx->buf_wr_ix - ctx->buf_rd_ix)
414
1.64k
                    return 0; /* need more data */
415
416
26.1k
            code = jbig2_parse_segment(ctx, segment, ctx->buf + ctx->buf_rd_ix);
417
26.1k
            ctx->buf_rd_ix += segment->data_length;
418
26.1k
            ctx->segment_index++;
419
26.1k
            if (ctx->state == JBIG2_FILE_RANDOM_BODIES) {
420
378
                if (ctx->segment_index == ctx->n_segments)
421
0
                    ctx->state = JBIG2_FILE_EOF;
422
25.8k
            } else {            /* JBIG2_FILE_SEQUENTIAL_BODY */
423
25.8k
                ctx->state = JBIG2_FILE_SEQUENTIAL_HEADER;
424
25.8k
            }
425
26.1k
            if (code < 0) {
426
481
                ctx->state = JBIG2_FILE_EOF;
427
481
                return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode; treating as end of file");
428
481
            }
429
25.6k
            break;
430
25.6k
        case JBIG2_FILE_EOF:
431
0
            if (ctx->buf_rd_ix == ctx->buf_wr_ix)
432
0
                return 0;
433
0
            return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, JBIG2_UNKNOWN_SEGMENT_NUMBER, "garbage beyond end of file");
434
64.6k
        }
435
64.6k
    }
436
2.96k
}
437
438
Jbig2Allocator *
439
jbig2_ctx_free(Jbig2Ctx *ctx)
440
2.96k
{
441
2.96k
    Jbig2Allocator *ca;
442
2.96k
    uint32_t i;
443
444
2.96k
    if (ctx == NULL)
445
0
        return NULL;
446
447
2.96k
    ca = ctx->allocator;
448
2.96k
    jbig2_free(ca, ctx->buf);
449
2.96k
    if (ctx->segments != NULL) {
450
36.0k
        for (i = 0; i < ctx->n_segments; i++)
451
33.0k
            jbig2_free_segment(ctx, ctx->segments[i]);
452
2.96k
        jbig2_free(ca, ctx->segments);
453
2.96k
    }
454
455
2.96k
    if (ctx->pages != NULL) {
456
8.46k
        for (i = 0; i <= ctx->current_page; i++)
457
5.50k
            if (ctx->pages[i].image != NULL)
458
3.07k
                jbig2_image_release(ctx, ctx->pages[i].image);
459
2.96k
        jbig2_free(ca, ctx->pages);
460
2.96k
    }
461
462
2.96k
    jbig2_free(ca, ctx);
463
464
2.96k
    return ca;
465
2.96k
}
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
13.1M
{
493
13.1M
    Jbig2WordStreamBuf *z = (Jbig2WordStreamBuf *) self;
494
13.1M
    uint32_t val = 0;
495
13.1M
    int ret = 0;
496
497
13.1M
    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
13.1M
    if (offset >= z->size) {
501
12.7M
        *word = 0;
502
12.7M
        return 0;
503
12.7M
    }
504
505
410k
    if (offset < z->size) {
506
410k
        val = (uint32_t) z->data[offset] << 24;
507
410k
        ret++;
508
410k
    }
509
410k
    if (offset + 1 < z->size) {
510
408k
        val |= (uint32_t) z->data[offset + 1] << 16;
511
408k
        ret++;
512
408k
    }
513
410k
    if (offset + 2 < z->size) {
514
406k
        val |= (uint32_t) z->data[offset + 2] << 8;
515
406k
        ret++;
516
406k
    }
517
410k
    if (offset + 3 < z->size) {
518
404k
        val |= z->data[offset + 3];
519
404k
        ret++;
520
404k
    }
521
410k
    *word = val;
522
410k
    return ret;
523
13.1M
}
524
525
Jbig2WordStream *
526
jbig2_word_stream_buf_new(Jbig2Ctx *ctx, const byte *data, size_t size)
527
13.5k
{
528
13.5k
    Jbig2WordStreamBuf *result = jbig2_new(ctx, Jbig2WordStreamBuf, 1);
529
530
13.5k
    if (result == NULL) {
531
6
        jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to allocate word stream");
532
6
        return NULL;
533
6
    }
534
535
13.5k
    result->super.get_next_word = jbig2_word_stream_buf_get_next_word;
536
13.5k
    result->data = data;
537
13.5k
    result->size = size;
538
539
13.5k
    return &result->super;
540
13.5k
}
541
542
void
543
jbig2_word_stream_buf_free(Jbig2Ctx *ctx, Jbig2WordStream *ws)
544
13.8k
{
545
13.8k
    jbig2_free(ctx->allocator, ws);
546
13.8k
}
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
22.8M
{
560
22.8M
    allocator->free(allocator, p);
561
22.8M
}
562
563
void *
564
jbig2_realloc(Jbig2Allocator *allocator, void *p, size_t size, size_t num)
565
2.62k
{
566
    /* check for integer multiplication overflow */
567
2.62k
    if (num > 0 && size >= SIZE_MAX / num)
568
0
        return NULL;
569
2.62k
    return allocator->realloc(allocator, p, size * num);
570
2.62k
}