Blame jbig2.c

Packit 3f21c4
/* Copyright (C) 2001-2012 Artifex Software, Inc.
Packit 3f21c4
   All Rights Reserved.
Packit 3f21c4
Packit 3f21c4
   This software is provided AS-IS with no warranty, either express or
Packit 3f21c4
   implied.
Packit 3f21c4
Packit 3f21c4
   This software is distributed under license and may not be copied,
Packit 3f21c4
   modified or distributed except as expressly authorized under the terms
Packit 3f21c4
   of the license contained in the file LICENSE in this distribution.
Packit 3f21c4
Packit 3f21c4
   Refer to licensing information at http://www.artifex.com or contact
Packit 3f21c4
   Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134, San Rafael,
Packit 3f21c4
   CA  94903, U.S.A., +1(415)492-9861, for further information.
Packit 3f21c4
*/
Packit 3f21c4
Packit 3f21c4
/*
Packit 3f21c4
    jbig2dec
Packit 3f21c4
*/
Packit 3f21c4
Packit 3f21c4
#ifdef HAVE_CONFIG_H
Packit 3f21c4
#include "config.h"
Packit 3f21c4
#endif
Packit 3f21c4
#include "os_types.h"
Packit 3f21c4
Packit 3f21c4
#include <stdio.h>
Packit 3f21c4
#include <stdlib.h>
Packit 3f21c4
#include <stdarg.h>
Packit 3f21c4
#include <string.h>
Packit 3f21c4
Packit 3f21c4
#include "jbig2.h"
Packit 3f21c4
#include "jbig2_priv.h"
Packit 3f21c4
Packit 3f21c4
static void *
Packit 3f21c4
jbig2_default_alloc(Jbig2Allocator *allocator, size_t size)
Packit 3f21c4
{
Packit 3f21c4
    return malloc(size);
Packit 3f21c4
}
Packit 3f21c4
Packit 3f21c4
static void
Packit 3f21c4
jbig2_default_free(Jbig2Allocator *allocator, void *p)
Packit 3f21c4
{
Packit 3f21c4
    free(p);
Packit 3f21c4
}
Packit 3f21c4
Packit 3f21c4
static void *
Packit 3f21c4
jbig2_default_realloc(Jbig2Allocator *allocator, void *p, size_t size)
Packit 3f21c4
{
Packit 3f21c4
    return realloc(p, size);
Packit 3f21c4
}
Packit 3f21c4
Packit 3f21c4
static Jbig2Allocator jbig2_default_allocator = {
Packit 3f21c4
    jbig2_default_alloc,
Packit 3f21c4
    jbig2_default_free,
Packit 3f21c4
    jbig2_default_realloc
Packit 3f21c4
};
Packit 3f21c4
Packit 3f21c4
void *
Packit 3f21c4
jbig2_alloc(Jbig2Allocator *allocator, size_t size, size_t num)
Packit 3f21c4
{
Packit 3f21c4
    /* check for integer multiplication overflow */
Packit 3f21c4
    if (num > 0 && size >= (size_t) - 0x100 / num)
Packit 3f21c4
        return NULL;
Packit 3f21c4
    return allocator->alloc(allocator, size * num);
Packit 3f21c4
}
Packit 3f21c4
Packit 3f21c4
/* jbig2_free and jbig2_realloc moved to the bottom of this file */
Packit 3f21c4
Packit 3f21c4
static int
Packit 3f21c4
jbig2_default_error(void *data, const char *msg, Jbig2Severity severity, int32_t seg_idx)
Packit 3f21c4
{
Packit 3f21c4
    /* report only fatal errors by default */
Packit 3f21c4
    if (severity == JBIG2_SEVERITY_FATAL) {
Packit 3f21c4
        fprintf(stderr, "jbig2 decoder FATAL ERROR: %s", msg);
Packit 3f21c4
        if (seg_idx != -1)
Packit 3f21c4
            fprintf(stderr, " (segment 0x%02x)", seg_idx);
Packit 3f21c4
        fprintf(stderr, "\n");
Packit 3f21c4
        fflush(stderr);
Packit 3f21c4
    }
Packit 3f21c4
Packit 3f21c4
    return 0;
Packit 3f21c4
}
Packit 3f21c4
Packit 3f21c4
int
Packit 3f21c4
jbig2_error(Jbig2Ctx *ctx, Jbig2Severity severity, int32_t segment_number, const char *fmt, ...)
Packit 3f21c4
{
Packit 3f21c4
    char buf[1024];
Packit 3f21c4
    va_list ap;
Packit 3f21c4
    int n;
Packit 3f21c4
    int code;
Packit 3f21c4
Packit 3f21c4
    va_start(ap, fmt);
Packit 3f21c4
    n = vsnprintf(buf, sizeof(buf), fmt, ap);
Packit 3f21c4
    va_end(ap);
Packit 3f21c4
    if (n < 0 || n == sizeof(buf))
Packit 3f21c4
        strncpy(buf, "jbig2_error: error in generating error string", sizeof(buf));
Packit 3f21c4
    code = ctx->error_callback(ctx->error_callback_data, buf, severity, segment_number);
Packit 3f21c4
    if (severity == JBIG2_SEVERITY_FATAL)
Packit 3f21c4
        code = -1;
Packit 3f21c4
    return code;
Packit 3f21c4
}
Packit 3f21c4
Packit 3f21c4
Jbig2Ctx *
Packit 3f21c4
jbig2_ctx_new(Jbig2Allocator *allocator, Jbig2Options options, Jbig2GlobalCtx *global_ctx, Jbig2ErrorCallback error_callback, void *error_callback_data)
Packit 3f21c4
{
Packit 3f21c4
    Jbig2Ctx *result;
Packit 3f21c4
Packit 3f21c4
    if (allocator == NULL)
Packit 3f21c4
        allocator = &jbig2_default_allocator;
Packit 3f21c4
    if (error_callback == NULL)
Packit 3f21c4
        error_callback = &jbig2_default_error;
Packit 3f21c4
Packit 3f21c4
    result = (Jbig2Ctx *) jbig2_alloc(allocator, sizeof(Jbig2Ctx), 1);
Packit 3f21c4
    if (result == NULL) {
Packit 3f21c4
        error_callback(error_callback_data, "initial context allocation failed!", JBIG2_SEVERITY_FATAL, -1);
Packit 3f21c4
        return result;
Packit 3f21c4
    }
Packit 3f21c4
Packit 3f21c4
    result->allocator = allocator;
Packit 3f21c4
    result->options = options;
Packit 3f21c4
    result->global_ctx = (const Jbig2Ctx *)global_ctx;
Packit 3f21c4
    result->error_callback = error_callback;
Packit 3f21c4
    result->error_callback_data = error_callback_data;
Packit 3f21c4
Packit 3f21c4
    result->state = (options & JBIG2_OPTIONS_EMBEDDED) ? JBIG2_FILE_SEQUENTIAL_HEADER : JBIG2_FILE_HEADER;
Packit 3f21c4
Packit 3f21c4
    result->buf = NULL;
Packit 3f21c4
Packit 3f21c4
    result->n_segments = 0;
Packit 3f21c4
    result->n_segments_max = 16;
Packit 3f21c4
    result->segments = jbig2_new(result, Jbig2Segment *, result->n_segments_max);
Packit 3f21c4
    if (result->segments == NULL) {
Packit 3f21c4
        error_callback(error_callback_data, "initial segments allocation failed!", JBIG2_SEVERITY_FATAL, -1);
Packit 3f21c4
        jbig2_free(allocator, result);
Packit 3f21c4
        return result;
Packit 3f21c4
    }
Packit 3f21c4
    result->segment_index = 0;
Packit 3f21c4
Packit 3f21c4
    result->current_page = 0;
Packit 3f21c4
    result->max_page_index = 4;
Packit 3f21c4
    result->pages = jbig2_new(result, Jbig2Page, result->max_page_index);
Packit 3f21c4
    if (result->pages == NULL) {
Packit 3f21c4
        error_callback(error_callback_data, "initial pages allocation failed!", JBIG2_SEVERITY_FATAL, -1);
Packit 3f21c4
        jbig2_free(allocator, result->segments);
Packit 3f21c4
        jbig2_free(allocator, result);
Packit 3f21c4
        return result;
Packit 3f21c4
    }
Packit 3f21c4
    {
Packit 3f21c4
        int index;
Packit 3f21c4
Packit 3f21c4
        for (index = 0; index < result->max_page_index; index++) {
Packit 3f21c4
            result->pages[index].state = JBIG2_PAGE_FREE;
Packit 3f21c4
            result->pages[index].number = 0;
Packit 3f21c4
            result->pages[index].image = NULL;
Packit 3f21c4
        }
Packit 3f21c4
    }
Packit 3f21c4
Packit 3f21c4
    return result;
Packit 3f21c4
}
Packit 3f21c4
Packit 3f21c4
#define get_uint16(bptr)\
Packit 3f21c4
  (((bptr)[0] << 8) | (bptr)[1])
Packit 3f21c4
#define get_int16(bptr)\
Packit 3f21c4
  (((int)get_uint16(bptr) ^ 0x8000) - 0x8000)
Packit 3f21c4
Packit 3f21c4
int16_t
Packit 3f21c4
jbig2_get_int16(const byte *bptr)
Packit 3f21c4
{
Packit 3f21c4
    return get_int16(bptr);
Packit 3f21c4
}
Packit 3f21c4
Packit 3f21c4
uint16_t
Packit 3f21c4
jbig2_get_uint16(const byte *bptr)
Packit 3f21c4
{
Packit 3f21c4
    return get_uint16(bptr);
Packit 3f21c4
}
Packit 3f21c4
Packit 3f21c4
int32_t
Packit 3f21c4
jbig2_get_int32(const byte *bptr)
Packit 3f21c4
{
Packit 3f21c4
    return ((int32_t) get_int16(bptr) << 16) | get_uint16(bptr + 2);
Packit 3f21c4
}
Packit 3f21c4
Packit 3f21c4
uint32_t
Packit 3f21c4
jbig2_get_uint32(const byte *bptr)
Packit 3f21c4
{
Packit 3f21c4
    return ((uint32_t) get_uint16(bptr) << 16) | get_uint16(bptr + 2);
Packit 3f21c4
}
Packit 3f21c4
Packit 3f21c4
/**
Packit 3f21c4
 * jbig2_data_in: submit data for decoding
Packit 3f21c4
 * @ctx: The jbig2dec decoder context
Packit 3f21c4
 * @data: a pointer to the data buffer
Packit 3f21c4
 * @size: the size of the data buffer in bytes
Packit 3f21c4
 *
Packit 3f21c4
 * Copies the specified data into internal storage and attempts
Packit 3f21c4
 * to (continue to) parse it as part of a jbig2 data stream.
Packit 3f21c4
 *
Packit 3f21c4
 * Return code: 0 on success
Packit 3f21c4
 *             -1 if there is a parsing error, or whatever
Packit 3f21c4
 *                the error handling callback returns
Packit 3f21c4
 **/
Packit 3f21c4
int
Packit 3f21c4
jbig2_data_in(Jbig2Ctx *ctx, const unsigned char *data, size_t size)
Packit 3f21c4
{
Packit 3f21c4
    const size_t initial_buf_size = 1024;
Packit 3f21c4
Packit 3f21c4
    if (ctx->buf == NULL) {
Packit 3f21c4
        size_t buf_size = initial_buf_size;
Packit 3f21c4
Packit 3f21c4
        do
Packit 3f21c4
            buf_size <<= 1;
Packit 3f21c4
        while (buf_size < size);
Packit 3f21c4
        ctx->buf = jbig2_new(ctx, byte, buf_size);
Packit 3f21c4
        if (ctx->buf == NULL) {
Packit 3f21c4
            return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to allocate ctx->buf in jbig2_data_in");
Packit 3f21c4
        }
Packit 3f21c4
        ctx->buf_size = buf_size;
Packit 3f21c4
        ctx->buf_rd_ix = 0;
Packit 3f21c4
        ctx->buf_wr_ix = 0;
Packit 3f21c4
    } else if (ctx->buf_wr_ix + size > ctx->buf_size) {
Packit 3f21c4
        if (ctx->buf_rd_ix <= (ctx->buf_size >> 1) && ctx->buf_wr_ix - ctx->buf_rd_ix + size <= ctx->buf_size) {
Packit 3f21c4
            memmove(ctx->buf, ctx->buf + ctx->buf_rd_ix, ctx->buf_wr_ix - ctx->buf_rd_ix);
Packit 3f21c4
        } else {
Packit 3f21c4
            byte *buf;
Packit 3f21c4
            size_t buf_size = initial_buf_size;
Packit 3f21c4
Packit 3f21c4
            do
Packit 3f21c4
                buf_size <<= 1;
Packit 3f21c4
            while (buf_size < ctx->buf_wr_ix - ctx->buf_rd_ix + size);
Packit 3f21c4
            buf = jbig2_new(ctx, byte, buf_size);
Packit 3f21c4
            if (buf == NULL) {
Packit 3f21c4
                return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to allocate buf in jbig2_data_in");
Packit 3f21c4
            }
Packit 3f21c4
            memcpy(buf, ctx->buf + ctx->buf_rd_ix, ctx->buf_wr_ix - ctx->buf_rd_ix);
Packit 3f21c4
            jbig2_free(ctx->allocator, ctx->buf);
Packit 3f21c4
            ctx->buf = buf;
Packit 3f21c4
            ctx->buf_size = buf_size;
Packit 3f21c4
        }
Packit 3f21c4
        ctx->buf_wr_ix -= ctx->buf_rd_ix;
Packit 3f21c4
        ctx->buf_rd_ix = 0;
Packit 3f21c4
    }
Packit 3f21c4
    memcpy(ctx->buf + ctx->buf_wr_ix, data, size);
Packit 3f21c4
    ctx->buf_wr_ix += size;
Packit 3f21c4
Packit 3f21c4
    /* data has now been added to buffer */
Packit 3f21c4
Packit 3f21c4
    for (;;) {
Packit 3f21c4
        const byte jbig2_id_string[8] = { 0x97, 0x4a, 0x42, 0x32, 0x0d, 0x0a, 0x1a, 0x0a };
Packit 3f21c4
        Jbig2Segment *segment;
Packit 3f21c4
        size_t header_size;
Packit 3f21c4
        int code;
Packit 3f21c4
Packit 3f21c4
        switch (ctx->state) {
Packit 3f21c4
        case JBIG2_FILE_HEADER:
Packit 3f21c4
            /* D.4.1 */
Packit 3f21c4
            if (ctx->buf_wr_ix - ctx->buf_rd_ix < 9)
Packit 3f21c4
                return 0;
Packit 3f21c4
            if (memcmp(ctx->buf + ctx->buf_rd_ix, jbig2_id_string, 8))
Packit 3f21c4
                return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "Not a JBIG2 file header");
Packit 3f21c4
            /* D.4.2 */
Packit 3f21c4
            ctx->file_header_flags = ctx->buf[ctx->buf_rd_ix + 8];
Packit 3f21c4
            if (ctx->file_header_flags & 0xFC) {
Packit 3f21c4
                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "reserved bits (2-7) of file header flags are not zero (0x%02x)", ctx->file_header_flags);
Packit 3f21c4
            }
Packit 3f21c4
            /* D.4.3 */
Packit 3f21c4
            if (!(ctx->file_header_flags & 2)) {        /* number of pages is known */
Packit 3f21c4
                if (ctx->buf_wr_ix - ctx->buf_rd_ix < 13)
Packit 3f21c4
                    return 0;
Packit 3f21c4
                ctx->n_pages = jbig2_get_uint32(ctx->buf + ctx->buf_rd_ix + 9);
Packit 3f21c4
                ctx->buf_rd_ix += 13;
Packit 3f21c4
                if (ctx->n_pages == 1)
Packit 3f21c4
                    jbig2_error(ctx, JBIG2_SEVERITY_INFO, -1, "file header indicates a single page document");
Packit 3f21c4
                else
Packit 3f21c4
                    jbig2_error(ctx, JBIG2_SEVERITY_INFO, -1, "file header indicates a %d page document", ctx->n_pages);
Packit 3f21c4
            } else {            /* number of pages not known */
Packit 3f21c4
Packit 3f21c4
                ctx->n_pages = 0;
Packit 3f21c4
                ctx->buf_rd_ix += 9;
Packit 3f21c4
            }
Packit 3f21c4
            /* determine the file organization based on the flags - D.4.2 again */
Packit 3f21c4
            if (ctx->file_header_flags & 1) {
Packit 3f21c4
                ctx->state = JBIG2_FILE_SEQUENTIAL_HEADER;
Packit 3f21c4
                jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1, "file header indicates sequential organization");
Packit 3f21c4
            } else {
Packit 3f21c4
                ctx->state = JBIG2_FILE_RANDOM_HEADERS;
Packit 3f21c4
                jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1, "file header indicates random-access organization");
Packit 3f21c4
Packit 3f21c4
            }
Packit 3f21c4
            break;
Packit 3f21c4
        case JBIG2_FILE_SEQUENTIAL_HEADER:
Packit 3f21c4
        case JBIG2_FILE_RANDOM_HEADERS:
Packit 3f21c4
            segment = jbig2_parse_segment_header(ctx, ctx->buf + ctx->buf_rd_ix, ctx->buf_wr_ix - ctx->buf_rd_ix, &header_size);
Packit 3f21c4
            if (segment == NULL)
Packit 3f21c4
                return 0;       /* need more data */
Packit 3f21c4
            ctx->buf_rd_ix += header_size;
Packit 3f21c4
Packit 3f21c4
            if (ctx->n_segments == ctx->n_segments_max)
Packit 3f21c4
                ctx->segments = jbig2_renew(ctx, ctx->segments, Jbig2Segment *, (ctx->n_segments_max <<= 2));
Packit 3f21c4
Packit 3f21c4
            ctx->segments[ctx->n_segments++] = segment;
Packit 3f21c4
            if (ctx->state == JBIG2_FILE_RANDOM_HEADERS) {
Packit 3f21c4
                if ((segment->flags & 63) == 51)        /* end of file */
Packit 3f21c4
                    ctx->state = JBIG2_FILE_RANDOM_BODIES;
Packit 3f21c4
            } else              /* JBIG2_FILE_SEQUENTIAL_HEADER */
Packit 3f21c4
                ctx->state = JBIG2_FILE_SEQUENTIAL_BODY;
Packit 3f21c4
            break;
Packit 3f21c4
        case JBIG2_FILE_SEQUENTIAL_BODY:
Packit 3f21c4
        case JBIG2_FILE_RANDOM_BODIES:
Packit 3f21c4
            segment = ctx->segments[ctx->segment_index];
Packit 3f21c4
            if (segment->data_length > ctx->buf_wr_ix - ctx->buf_rd_ix)
Packit 3f21c4
                return 0;       /* need more data */
Packit 3f21c4
            code = jbig2_parse_segment(ctx, segment, ctx->buf + ctx->buf_rd_ix);
Packit 3f21c4
            ctx->buf_rd_ix += segment->data_length;
Packit 3f21c4
            ctx->segment_index++;
Packit 3f21c4
            if (ctx->state == JBIG2_FILE_RANDOM_BODIES) {
Packit 3f21c4
                if (ctx->segment_index == ctx->n_segments)
Packit 3f21c4
                    ctx->state = JBIG2_FILE_EOF;
Packit 3f21c4
            } else {            /* JBIG2_FILE_SEQUENCIAL_BODY */
Packit 3f21c4
Packit 3f21c4
                ctx->state = JBIG2_FILE_SEQUENTIAL_HEADER;
Packit 3f21c4
            }
Packit 3f21c4
            if (code < 0) {
Packit 3f21c4
                ctx->state = JBIG2_FILE_EOF;
Packit 3f21c4
                return code;
Packit 3f21c4
            }
Packit 3f21c4
            break;
Packit 3f21c4
        case JBIG2_FILE_EOF:
Packit 3f21c4
            if (ctx->buf_rd_ix == ctx->buf_wr_ix)
Packit 3f21c4
                return 0;
Packit 3f21c4
            return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "Garbage beyond end of file");
Packit 3f21c4
        }
Packit 3f21c4
    }
Packit 3f21c4
}
Packit 3f21c4
Packit 3f21c4
void
Packit 3f21c4
jbig2_ctx_free(Jbig2Ctx *ctx)
Packit 3f21c4
{
Packit 3f21c4
    Jbig2Allocator *ca = ctx->allocator;
Packit 3f21c4
    int i;
Packit 3f21c4
Packit 3f21c4
    jbig2_free(ca, ctx->buf);
Packit 3f21c4
    if (ctx->segments != NULL) {
Packit 3f21c4
        for (i = 0; i < ctx->n_segments; i++)
Packit 3f21c4
            jbig2_free_segment(ctx, ctx->segments[i]);
Packit 3f21c4
        jbig2_free(ca, ctx->segments);
Packit 3f21c4
    }
Packit 3f21c4
Packit 3f21c4
    if (ctx->pages != NULL) {
Packit 3f21c4
        for (i = 0; i <= ctx->current_page; i++)
Packit 3f21c4
            if (ctx->pages[i].image != NULL)
Packit 3f21c4
                jbig2_image_release(ctx, ctx->pages[i].image);
Packit 3f21c4
        jbig2_free(ca, ctx->pages);
Packit 3f21c4
    }
Packit 3f21c4
Packit 3f21c4
    jbig2_free(ca, ctx);
Packit 3f21c4
}
Packit 3f21c4
Packit 3f21c4
Jbig2GlobalCtx *
Packit 3f21c4
jbig2_make_global_ctx(Jbig2Ctx *ctx)
Packit 3f21c4
{
Packit 3f21c4
    return (Jbig2GlobalCtx *) ctx;
Packit 3f21c4
}
Packit 3f21c4
Packit 3f21c4
void
Packit 3f21c4
jbig2_global_ctx_free(Jbig2GlobalCtx *global_ctx)
Packit 3f21c4
{
Packit 3f21c4
    jbig2_ctx_free((Jbig2Ctx *) global_ctx);
Packit 3f21c4
}
Packit 3f21c4
Packit 3f21c4
/* I'm not committed to keeping the word stream interface. It's handy
Packit 3f21c4
   when you think you may be streaming your input, but if you're not
Packit 3f21c4
   (as is currently the case), it just adds complexity.
Packit 3f21c4
*/
Packit 3f21c4
Packit 3f21c4
typedef struct {
Packit 3f21c4
    Jbig2WordStream super;
Packit 3f21c4
    const byte *data;
Packit 3f21c4
    size_t size;
Packit 3f21c4
} Jbig2WordStreamBuf;
Packit 3f21c4
Packit 3f21c4
static void
Packit 3f21c4
jbig2_word_stream_buf_get_next_word(Jbig2WordStream *self, size_t offset, uint32_t *word)
Packit 3f21c4
{
Packit 3f21c4
    Jbig2WordStreamBuf *z = (Jbig2WordStreamBuf *) self;
Packit 3f21c4
    const byte *data = z->data;
Packit 3f21c4
Packit 3f21c4
    *word = 0;
Packit 3f21c4
    if (offset + 4 < z->size)
Packit 3f21c4
        *word = (data[offset] << 24) | (data[offset + 1] << 16) | (data[offset + 2] << 8) | data[offset + 3];
Packit 3f21c4
    else if (offset <= z->size) {
Packit 3f21c4
        size_t i;
Packit 3f21c4
Packit 3f21c4
        for (i = 0; i < z->size - offset; i++)
Packit 3f21c4
            *word |= data[offset + i] << ((3 - i) << 3);
Packit 3f21c4
    }
Packit 3f21c4
}
Packit 3f21c4
Packit 3f21c4
Jbig2WordStream *
Packit 3f21c4
jbig2_word_stream_buf_new(Jbig2Ctx *ctx, const byte *data, size_t size)
Packit 3f21c4
{
Packit 3f21c4
    Jbig2WordStreamBuf *result = jbig2_new(ctx, Jbig2WordStreamBuf, 1);
Packit 3f21c4
Packit 3f21c4
    if (result == NULL) {
Packit 3f21c4
        jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to allocate Jbig2WordStreamBuf in jbig2_word_stream_buf_new");
Packit 3f21c4
        return NULL;
Packit 3f21c4
    }
Packit 3f21c4
Packit 3f21c4
    result->super.get_next_word = jbig2_word_stream_buf_get_next_word;
Packit 3f21c4
    result->data = data;
Packit 3f21c4
    result->size = size;
Packit 3f21c4
Packit 3f21c4
    return &result->super;
Packit 3f21c4
}
Packit 3f21c4
Packit 3f21c4
void
Packit 3f21c4
jbig2_word_stream_buf_free(Jbig2Ctx *ctx, Jbig2WordStream *ws)
Packit 3f21c4
{
Packit 3f21c4
    jbig2_free(ctx->allocator, ws);
Packit 3f21c4
}
Packit 3f21c4
Packit 3f21c4
/* When Memento is in use, the ->free and ->realloc calls get
Packit 3f21c4
 * turned into ->Memento_free and ->Memento_realloc, which is
Packit 3f21c4
 * obviously problematic. Undefine free and realloc here to
Packit 3f21c4
 * avoid this. */
Packit 3f21c4
#ifdef MEMENTO
Packit 3f21c4
#undef free
Packit 3f21c4
#undef realloc
Packit 3f21c4
#endif
Packit 3f21c4
Packit 3f21c4
void
Packit 3f21c4
jbig2_free(Jbig2Allocator *allocator, void *p)
Packit 3f21c4
{
Packit 3f21c4
    allocator->free(allocator, p);
Packit 3f21c4
}
Packit 3f21c4
Packit 3f21c4
void *
Packit 3f21c4
jbig2_realloc(Jbig2Allocator *allocator, void *p, size_t size, size_t num)
Packit 3f21c4
{
Packit 3f21c4
    /* check for integer multiplication overflow */
Packit 3f21c4
    if (num > 0 && size >= (size_t) - 0x100 / num)
Packit 3f21c4
        return NULL;
Packit 3f21c4
    return allocator->realloc(allocator, p, size * num);
Packit 3f21c4
}