Coverage Report

Created: 2025-07-23 06:37

/src/mupdf/thirdparty/jbig2dec/jbig2.c
Line
Count
Source (jump to first uncovered line)
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
26.4k
{
64
    /* Check for integer multiplication overflow when computing
65
    the full size of the allocation. */
66
26.4k
    if (num > 0 && size > SIZE_MAX / num)
67
0
        return NULL;
68
26.4k
    return allocator->alloc(allocator, size * num);
69
26.4k
}
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
29.1k
{
89
29.1k
    char buf[1024];
90
29.1k
    va_list ap;
91
29.1k
    int n;
92
93
29.1k
    va_start(ap, fmt);
94
29.1k
    n = vsnprintf(buf, sizeof(buf), fmt, ap);
95
29.1k
    va_end(ap);
96
29.1k
    if (n < 0 || n == sizeof(buf))
97
0
        strncpy(buf, "failed to generate error string", sizeof(buf));
98
29.1k
    ctx->error_callback(ctx->error_callback_data, buf, severity, segment_number);
99
29.1k
    return -1;
100
29.1k
}
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
84
{
105
84
    Jbig2Ctx *result;
106
107
84
    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
84
    if (allocator == NULL)
117
0
        allocator = &jbig2_default_allocator;
118
84
    if (error_callback == NULL)
119
0
        error_callback = &jbig2_default_error;
120
121
84
    result = (Jbig2Ctx *) jbig2_alloc(allocator, sizeof(Jbig2Ctx), 1);
122
84
    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
84
    result->allocator = allocator;
128
84
    result->options = options;
129
84
    result->global_ctx = (const Jbig2Ctx *)global_ctx;
130
84
    result->error_callback = error_callback;
131
84
    result->error_callback_data = error_callback_data;
132
133
84
    result->state = (options & JBIG2_OPTIONS_EMBEDDED) ? JBIG2_FILE_SEQUENTIAL_HEADER : JBIG2_FILE_HEADER;
134
135
84
    result->buf = NULL;
136
137
84
    result->n_segments = 0;
138
84
    result->n_segments_max = 16;
139
84
    result->segments = jbig2_new(result, Jbig2Segment *, result->n_segments_max);
140
84
    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
84
    result->segment_index = 0;
146
147
84
    result->current_page = 0;
148
84
    result->max_page_index = 4;
149
84
    result->pages = jbig2_new(result, Jbig2Page, result->max_page_index);
150
84
    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
84
    {
157
84
        uint32_t index;
158
159
420
        for (index = 0; index < result->max_page_index; index++) {
160
336
            result->pages[index].state = JBIG2_PAGE_FREE;
161
336
            result->pages[index].number = 0;
162
336
            result->pages[index].width = 0;
163
336
            result->pages[index].height = 0xffffffff;
164
336
            result->pages[index].x_resolution = 0;
165
336
            result->pages[index].y_resolution = 0;
166
336
            result->pages[index].stripe_size = 0;
167
336
            result->pages[index].striped = 0;
168
336
            result->pages[index].end_row = 0;
169
336
            result->pages[index].flags = 0;
170
336
            result->pages[index].image = NULL;
171
336
        }
172
84
    }
173
174
84
    return result;
175
84
}
176
177
#define get_uint16(bptr)\
178
3.20k
    (((bptr)[0] << 8) | (bptr)[1])
179
#define get_int16(bptr)\
180
73
    (((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
73
{
187
73
    return get_int16(bptr);
188
73
}
189
190
/* coverity[ -tainted_data_return ] */
191
/* coverity[ -tainted_data_argument : arg-0 ] */
192
uint16_t
193
jbig2_get_uint16(const byte *bptr)
194
86
{
195
86
    return get_uint16(bptr);
196
86
}
197
198
/* coverity[ -tainted_data_return ] */
199
/* coverity[ -tainted_data_argument : arg-0 ] */
200
int32_t
201
jbig2_get_int32(const byte *bptr)
202
0
{
203
0
    return ((int32_t) get_int16(bptr) << 16) | get_uint16(bptr + 2);
204
0
}
205
206
/* coverity[ -tainted_data_return ] */
207
/* coverity[ -tainted_data_argument : arg-0 ] */
208
uint32_t
209
jbig2_get_uint32(const byte *bptr)
210
1.52k
{
211
1.52k
    return ((uint32_t) get_uint16(bptr) << 16) | get_uint16(bptr + 2);
212
1.52k
}
213
214
static size_t
215
jbig2_find_buffer_size(size_t desired)
216
309
{
217
309
    const size_t initial_buf_size = 1024;
218
309
    size_t size = initial_buf_size;
219
220
309
    if (desired == SIZE_MAX)
221
0
        return SIZE_MAX;
222
223
1.36k
    while (size < desired)
224
1.05k
        size <<= 1;
225
226
309
    return size;
227
309
}
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
469
{
245
469
    if (ctx->buf == NULL) {
246
84
        size_t buf_size = jbig2_find_buffer_size(size);
247
84
        ctx->buf = jbig2_new(ctx, byte, buf_size);
248
84
        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
84
        ctx->buf_size = buf_size;
252
84
        ctx->buf_rd_ix = 0;
253
84
        ctx->buf_wr_ix = 0;
254
385
    } else if (size > ctx->buf_size - ctx->buf_wr_ix) {
255
225
        size_t already = ctx->buf_wr_ix - ctx->buf_rd_ix;
256
257
225
        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
225
        } else {
260
225
            byte *buf;
261
225
            size_t buf_size;
262
263
225
            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
225
            buf_size = jbig2_find_buffer_size(size + already);
268
269
225
            buf = jbig2_new(ctx, byte, buf_size);
270
225
            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
225
            memcpy(buf, ctx->buf + ctx->buf_rd_ix, already);
274
225
            jbig2_free(ctx->allocator, ctx->buf);
275
225
            ctx->buf = buf;
276
225
            ctx->buf_size = buf_size;
277
225
        }
278
225
        ctx->buf_wr_ix -= ctx->buf_rd_ix;
279
225
        ctx->buf_rd_ix = 0;
280
225
    }
281
282
469
    memcpy(ctx->buf + ctx->buf_wr_ix, data, size);
283
469
    ctx->buf_wr_ix += size;
284
285
    /* data has now been added to buffer */
286
287
896
    for (;;) {
288
896
        const byte jbig2_id_string[8] = { 0x97, 0x4a, 0x42, 0x32, 0x0d, 0x0a, 0x1a, 0x0a };
289
896
        Jbig2Segment *segment;
290
896
        size_t header_size;
291
896
        int code;
292
293
896
        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
269
        case JBIG2_FILE_SEQUENTIAL_HEADER:
335
269
        case JBIG2_FILE_RANDOM_HEADERS:
336
269
            segment = jbig2_parse_segment_header(ctx, ctx->buf + ctx->buf_rd_ix, ctx->buf_wr_ix - ctx->buf_rd_ix, &header_size);
337
269
            if (segment == NULL)
338
27
                return 0; /* need more data */
339
242
            ctx->buf_rd_ix += header_size;
340
341
242
            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
                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "too many segments in jbig2 image");
347
0
                }
348
0
                else if (ctx->n_segments_max > (UINT32_MAX >> 2)) {
349
0
                    ctx->n_segments_max = UINT32_MAX;
350
0
                }
351
352
0
                segments = jbig2_renew(ctx, ctx->segments, Jbig2Segment *, (ctx->n_segments_max <<= 2));
353
0
                if (segments == NULL) {
354
0
                    ctx->state = JBIG2_FILE_EOF;
355
0
                    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate space for more segments");
356
0
                }
357
0
                ctx->segments = segments;
358
0
            }
359
360
242
            ctx->segments[ctx->n_segments++] = segment;
361
242
            if (ctx->state == JBIG2_FILE_RANDOM_HEADERS) {
362
0
                if ((segment->flags & 63) == 51)        /* end of file */
363
0
                    ctx->state = JBIG2_FILE_RANDOM_BODIES;
364
0
            } else              /* JBIG2_FILE_SEQUENTIAL_HEADER */
365
242
                ctx->state = JBIG2_FILE_SEQUENTIAL_BODY;
366
242
            break;
367
627
        case JBIG2_FILE_SEQUENTIAL_BODY:
368
627
        case JBIG2_FILE_RANDOM_BODIES:
369
627
            segment = ctx->segments[ctx->segment_index];
370
371
            /* immediate generic regions may have unknown size */
372
627
            if (segment->data_length == 0xffffffff && (segment->flags & 63) == 38) {
373
4
                byte *s, *e, *p;
374
4
                int mmr;
375
4
                byte mmr_marker[2] = { 0x00, 0x00 };
376
4
                byte arith_marker[2] = { 0xff, 0xac };
377
4
                byte *desired_marker;
378
379
4
                s = p = ctx->buf + ctx->buf_rd_ix;
380
4
                e = ctx->buf + ctx->buf_wr_ix;
381
382
4
                if (e - p < 18)
383
0
                        return 0; /* need more data */
384
385
4
                mmr = p[17] & 1;
386
4
                p += 18;
387
4
                desired_marker = mmr ? mmr_marker : arith_marker;
388
389
                /* look for two byte marker */
390
4
                if (e - p < 2)
391
0
                    return 0; /* need more data */
392
393
524
                while (p[0] != desired_marker[0] || p[1] != desired_marker[1]) {
394
524
                    p++;
395
524
                    if (e - p < 2)
396
4
                        return 0; /* need more data */
397
524
                }
398
0
                p += 2;
399
400
                /* the marker is followed by a four byte row count */
401
0
                if (e - p < 4)
402
0
                        return 0; /* need more data */
403
0
                segment->rows = jbig2_get_uint32(p);
404
0
                p += 4;
405
406
0
                segment->data_length = (size_t) (p - s);
407
0
                jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "unknown length determined to be %lu", (long) segment->data_length);
408
0
            }
409
623
            else if (segment->data_length > ctx->buf_wr_ix - ctx->buf_rd_ix)
410
437
                    return 0; /* need more data */
411
412
186
            code = jbig2_parse_segment(ctx, segment, ctx->buf + ctx->buf_rd_ix);
413
186
            ctx->buf_rd_ix += segment->data_length;
414
186
            ctx->segment_index++;
415
186
            if (ctx->state == JBIG2_FILE_RANDOM_BODIES) {
416
0
                if (ctx->segment_index == ctx->n_segments)
417
0
                    ctx->state = JBIG2_FILE_EOF;
418
186
            } else {            /* JBIG2_FILE_SEQUENTIAL_BODY */
419
186
                ctx->state = JBIG2_FILE_SEQUENTIAL_HEADER;
420
186
            }
421
186
            if (code < 0) {
422
1
                ctx->state = JBIG2_FILE_EOF;
423
1
                return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode; treating as end of file");
424
1
            }
425
185
            break;
426
185
        case JBIG2_FILE_EOF:
427
0
            if (ctx->buf_rd_ix == ctx->buf_wr_ix)
428
0
                return 0;
429
0
            return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, JBIG2_UNKNOWN_SEGMENT_NUMBER, "garbage beyond end of file");
430
896
        }
431
896
    }
432
469
}
433
434
Jbig2Allocator *
435
jbig2_ctx_free(Jbig2Ctx *ctx)
436
84
{
437
84
    Jbig2Allocator *ca;
438
84
    uint32_t i;
439
440
84
    if (ctx == NULL)
441
0
        return NULL;
442
443
84
    ca = ctx->allocator;
444
84
    jbig2_free(ca, ctx->buf);
445
84
    if (ctx->segments != NULL) {
446
326
        for (i = 0; i < ctx->n_segments; i++)
447
242
            jbig2_free_segment(ctx, ctx->segments[i]);
448
84
        jbig2_free(ca, ctx->segments);
449
84
    }
450
451
84
    if (ctx->pages != NULL) {
452
168
        for (i = 0; i <= ctx->current_page; i++)
453
84
            if (ctx->pages[i].image != NULL)
454
73
                jbig2_image_release(ctx, ctx->pages[i].image);
455
84
        jbig2_free(ca, ctx->pages);
456
84
    }
457
458
84
    jbig2_free(ca, ctx);
459
460
84
    return ca;
461
84
}
462
463
Jbig2GlobalCtx *
464
jbig2_make_global_ctx(Jbig2Ctx *ctx)
465
0
{
466
0
    return (Jbig2GlobalCtx *) ctx;
467
0
}
468
469
Jbig2Allocator *
470
jbig2_global_ctx_free(Jbig2GlobalCtx *global_ctx)
471
0
{
472
0
    return jbig2_ctx_free((Jbig2Ctx *) global_ctx);
473
0
}
474
475
/* I'm not committed to keeping the word stream interface. It's handy
476
   when you think you may be streaming your input, but if you're not
477
   (as is currently the case), it just adds complexity.
478
*/
479
480
typedef struct {
481
    Jbig2WordStream super;
482
    const byte *data;
483
    size_t size;
484
} Jbig2WordStreamBuf;
485
486
static int
487
jbig2_word_stream_buf_get_next_word(Jbig2Ctx *ctx, Jbig2WordStream *self, size_t offset, uint32_t *word)
488
153k
{
489
153k
    Jbig2WordStreamBuf *z = (Jbig2WordStreamBuf *) self;
490
153k
    uint32_t val = 0;
491
153k
    int ret = 0;
492
493
153k
    if (self == NULL || word == NULL) {
494
0
        return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to read next word of stream because stream or output missing");
495
0
    }
496
153k
    if (offset >= z->size) {
497
3
        *word = 0;
498
3
        return 0;
499
3
    }
500
501
153k
    if (offset < z->size) {
502
153k
        val = (uint32_t) z->data[offset] << 24;
503
153k
        ret++;
504
153k
    }
505
153k
    if (offset + 1 < z->size) {
506
153k
        val |= (uint32_t) z->data[offset + 1] << 16;
507
153k
        ret++;
508
153k
    }
509
153k
    if (offset + 2 < z->size) {
510
153k
        val |= (uint32_t) z->data[offset + 2] << 8;
511
153k
        ret++;
512
153k
    }
513
153k
    if (offset + 3 < z->size) {
514
152k
        val |= z->data[offset + 3];
515
152k
        ret++;
516
152k
    }
517
153k
    *word = val;
518
153k
    return ret;
519
153k
}
520
521
Jbig2WordStream *
522
jbig2_word_stream_buf_new(Jbig2Ctx *ctx, const byte *data, size_t size)
523
116
{
524
116
    Jbig2WordStreamBuf *result = jbig2_new(ctx, Jbig2WordStreamBuf, 1);
525
526
116
    if (result == NULL) {
527
0
        jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to allocate word stream");
528
0
        return NULL;
529
0
    }
530
531
116
    result->super.get_next_word = jbig2_word_stream_buf_get_next_word;
532
116
    result->data = data;
533
116
    result->size = size;
534
535
116
    return &result->super;
536
116
}
537
538
void
539
jbig2_word_stream_buf_free(Jbig2Ctx *ctx, Jbig2WordStream *ws)
540
116
{
541
116
    jbig2_free(ctx->allocator, ws);
542
116
}
543
544
/* When Memento is in use, the ->free and ->realloc calls get
545
 * turned into ->Memento_free and ->Memento_realloc, which is
546
 * obviously problematic. Undefine free and realloc here to
547
 * avoid this. */
548
#ifdef MEMENTO
549
#undef free
550
#undef realloc
551
#endif
552
553
void
554
jbig2_free(Jbig2Allocator *allocator, void *p)
555
26.9k
{
556
26.9k
    allocator->free(allocator, p);
557
26.9k
}
558
559
void *
560
jbig2_realloc(Jbig2Allocator *allocator, void *p, size_t size, size_t num)
561
0
{
562
    /* check for integer multiplication overflow */
563
0
    if (num > 0 && size >= SIZE_MAX / num)
564
0
        return NULL;
565
0
    return allocator->realloc(allocator, p, size * num);
566
0
}