Coverage Report

Created: 2025-06-10 07:27

/src/ghostpdl/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
1.32k
{
64
    /* Check for integer multiplication overflow when computing
65
    the full size of the allocation. */
66
1.32k
    if (num > 0 && size > SIZE_MAX / num)
67
0
        return NULL;
68
1.32k
    return allocator->alloc(allocator, size * num);
69
1.32k
}
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
925
{
89
925
    char buf[1024];
90
925
    va_list ap;
91
925
    int n;
92
93
925
    va_start(ap, fmt);
94
925
    n = vsnprintf(buf, sizeof(buf), fmt, ap);
95
925
    va_end(ap);
96
925
    if (n < 0 || n == sizeof(buf))
97
0
        strncpy(buf, "failed to generate error string", sizeof(buf));
98
925
    ctx->error_callback(ctx->error_callback_data, buf, severity, segment_number);
99
925
    return -1;
100
925
}
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
64
{
105
64
    Jbig2Ctx *result;
106
107
64
    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
64
    if (allocator == NULL)
117
0
        allocator = &jbig2_default_allocator;
118
64
    if (error_callback == NULL)
119
0
        error_callback = &jbig2_default_error;
120
121
64
    result = (Jbig2Ctx *) jbig2_alloc(allocator, sizeof(Jbig2Ctx), 1);
122
64
    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
64
    result->allocator = allocator;
128
64
    result->options = options;
129
64
    result->global_ctx = (const Jbig2Ctx *)global_ctx;
130
64
    result->error_callback = error_callback;
131
64
    result->error_callback_data = error_callback_data;
132
133
64
    result->state = (options & JBIG2_OPTIONS_EMBEDDED) ? JBIG2_FILE_SEQUENTIAL_HEADER : JBIG2_FILE_HEADER;
134
135
64
    result->buf = NULL;
136
137
64
    result->n_segments = 0;
138
64
    result->n_segments_max = 16;
139
64
    result->segments = jbig2_new(result, Jbig2Segment *, result->n_segments_max);
140
64
    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
64
    result->segment_index = 0;
146
147
64
    result->current_page = 0;
148
64
    result->max_page_index = 4;
149
64
    result->pages = jbig2_new(result, Jbig2Page, result->max_page_index);
150
64
    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
64
    {
157
64
        uint32_t index;
158
159
320
        for (index = 0; index < result->max_page_index; index++) {
160
256
            result->pages[index].state = JBIG2_PAGE_FREE;
161
256
            result->pages[index].number = 0;
162
256
            result->pages[index].width = 0;
163
256
            result->pages[index].height = 0xffffffff;
164
256
            result->pages[index].x_resolution = 0;
165
256
            result->pages[index].y_resolution = 0;
166
256
            result->pages[index].stripe_size = 0;
167
256
            result->pages[index].striped = 0;
168
256
            result->pages[index].end_row = 0;
169
256
            result->pages[index].flags = 0;
170
256
            result->pages[index].image = NULL;
171
256
        }
172
64
    }
173
174
64
    return result;
175
64
}
176
177
#define get_uint16(bptr)\
178
1.75k
    (((bptr)[0] << 8) | (bptr)[1])
179
#define get_int16(bptr)\
180
61
    (((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
61
{
187
61
    return get_int16(bptr);
188
61
}
189
190
/* coverity[ -tainted_data_return ] */
191
/* coverity[ -tainted_data_argument : arg-0 ] */
192
uint16_t
193
jbig2_get_uint16(const byte *bptr)
194
15
{
195
15
    return get_uint16(bptr);
196
15
}
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
839
{
211
839
    return ((uint32_t) get_uint16(bptr) << 16) | get_uint16(bptr + 2);
212
839
}
213
214
static size_t
215
jbig2_find_buffer_size(size_t desired)
216
237
{
217
237
    const size_t initial_buf_size = 1024;
218
237
    size_t size = initial_buf_size;
219
220
237
    if (desired == SIZE_MAX)
221
0
        return SIZE_MAX;
222
223
877
    while (size < desired)
224
640
        size <<= 1;
225
226
237
    return size;
227
237
}
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
544
{
245
544
    if (ctx->buf == NULL) {
246
64
        size_t buf_size = jbig2_find_buffer_size(size);
247
64
        ctx->buf = jbig2_new(ctx, byte, buf_size);
248
64
        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
64
        ctx->buf_size = buf_size;
252
64
        ctx->buf_rd_ix = 0;
253
64
        ctx->buf_wr_ix = 0;
254
480
    } else if (size > ctx->buf_size - ctx->buf_wr_ix) {
255
173
        size_t already = ctx->buf_wr_ix - ctx->buf_rd_ix;
256
257
173
        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
173
        } else {
260
173
            byte *buf;
261
173
            size_t buf_size;
262
263
173
            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
173
            buf_size = jbig2_find_buffer_size(size + already);
268
269
173
            buf = jbig2_new(ctx, byte, buf_size);
270
173
            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
173
            memcpy(buf, ctx->buf + ctx->buf_rd_ix, already);
274
173
            jbig2_free(ctx->allocator, ctx->buf);
275
173
            ctx->buf = buf;
276
173
            ctx->buf_size = buf_size;
277
173
        }
278
173
        ctx->buf_wr_ix -= ctx->buf_rd_ix;
279
173
        ctx->buf_rd_ix = 0;
280
173
    }
281
282
544
    memcpy(ctx->buf + ctx->buf_wr_ix, data, size);
283
544
    ctx->buf_wr_ix += size;
284
285
    /* data has now been added to buffer */
286
287
816
    for (;;) {
288
816
        const byte jbig2_id_string[8] = { 0x97, 0x4a, 0x42, 0x32, 0x0d, 0x0a, 0x1a, 0x0a };
289
816
        Jbig2Segment *segment;
290
816
        size_t header_size;
291
816
        int code;
292
293
816
        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
185
        case JBIG2_FILE_SEQUENTIAL_HEADER:
335
185
        case JBIG2_FILE_RANDOM_HEADERS:
336
185
            segment = jbig2_parse_segment_header(ctx, ctx->buf + ctx->buf_rd_ix, ctx->buf_wr_ix - ctx->buf_rd_ix, &header_size);
337
185
            if (segment == NULL)
338
34
                return 0; /* need more data */
339
151
            ctx->buf_rd_ix += header_size;
340
341
151
            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
151
            ctx->segments[ctx->n_segments++] = segment;
365
151
            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
151
                ctx->state = JBIG2_FILE_SEQUENTIAL_BODY;
370
151
            break;
371
631
        case JBIG2_FILE_SEQUENTIAL_BODY:
372
631
        case JBIG2_FILE_RANDOM_BODIES:
373
631
            segment = ctx->segments[ctx->segment_index];
374
375
            /* immediate generic regions may have unknown size */
376
631
            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
631
            else if (segment->data_length > ctx->buf_wr_ix - ctx->buf_rd_ix)
414
507
                    return 0; /* need more data */
415
416
124
            code = jbig2_parse_segment(ctx, segment, ctx->buf + ctx->buf_rd_ix);
417
124
            ctx->buf_rd_ix += segment->data_length;
418
124
            ctx->segment_index++;
419
124
            if (ctx->state == JBIG2_FILE_RANDOM_BODIES) {
420
0
                if (ctx->segment_index == ctx->n_segments)
421
0
                    ctx->state = JBIG2_FILE_EOF;
422
124
            } else {            /* JBIG2_FILE_SEQUENTIAL_BODY */
423
124
                ctx->state = JBIG2_FILE_SEQUENTIAL_HEADER;
424
124
            }
425
124
            if (code < 0) {
426
3
                ctx->state = JBIG2_FILE_EOF;
427
3
                return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode; treating as end of file");
428
3
            }
429
121
            break;
430
121
        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
816
        }
435
816
    }
436
544
}
437
438
Jbig2Allocator *
439
jbig2_ctx_free(Jbig2Ctx *ctx)
440
64
{
441
64
    Jbig2Allocator *ca;
442
64
    uint32_t i;
443
444
64
    if (ctx == NULL)
445
0
        return NULL;
446
447
64
    ca = ctx->allocator;
448
64
    jbig2_free(ca, ctx->buf);
449
64
    if (ctx->segments != NULL) {
450
215
        for (i = 0; i < ctx->n_segments; i++)
451
151
            jbig2_free_segment(ctx, ctx->segments[i]);
452
64
        jbig2_free(ca, ctx->segments);
453
64
    }
454
455
64
    if (ctx->pages != NULL) {
456
128
        for (i = 0; i <= ctx->current_page; i++)
457
64
            if (ctx->pages[i].image != NULL)
458
61
                jbig2_image_release(ctx, ctx->pages[i].image);
459
64
        jbig2_free(ca, ctx->pages);
460
64
    }
461
462
64
    jbig2_free(ca, ctx);
463
464
64
    return ca;
465
64
}
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
250k
{
493
250k
    Jbig2WordStreamBuf *z = (Jbig2WordStreamBuf *) self;
494
250k
    uint32_t val = 0;
495
250k
    int ret = 0;
496
497
250k
    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
250k
    if (offset >= z->size) {
501
24
        *word = 0;
502
24
        return 0;
503
24
    }
504
505
250k
    if (offset < z->size) {
506
250k
        val = (uint32_t) z->data[offset] << 24;
507
250k
        ret++;
508
250k
    }
509
250k
    if (offset + 1 < z->size) {
510
250k
        val |= (uint32_t) z->data[offset + 1] << 16;
511
250k
        ret++;
512
250k
    }
513
250k
    if (offset + 2 < z->size) {
514
250k
        val |= (uint32_t) z->data[offset + 2] << 8;
515
250k
        ret++;
516
250k
    }
517
250k
    if (offset + 3 < z->size) {
518
250k
        val |= z->data[offset + 3];
519
250k
        ret++;
520
250k
    }
521
250k
    *word = val;
522
250k
    return ret;
523
250k
}
524
525
Jbig2WordStream *
526
jbig2_word_stream_buf_new(Jbig2Ctx *ctx, const byte *data, size_t size)
527
60
{
528
60
    Jbig2WordStreamBuf *result = jbig2_new(ctx, Jbig2WordStreamBuf, 1);
529
530
60
    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
60
    result->super.get_next_word = jbig2_word_stream_buf_get_next_word;
536
60
    result->data = data;
537
60
    result->size = size;
538
539
60
    return &result->super;
540
60
}
541
542
void
543
jbig2_word_stream_buf_free(Jbig2Ctx *ctx, Jbig2WordStream *ws)
544
60
{
545
60
    jbig2_free(ctx->allocator, ws);
546
60
}
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
1.54k
{
560
1.54k
    allocator->free(allocator, p);
561
1.54k
}
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
}