Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/base/sjbig2.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2022 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.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, for further information.
14
*/
15
16
17
/* jbig2decode filter implementation -- hooks in libjbig2dec */
18
19
#include "stdint_.h"
20
#include "memory_.h"
21
#include "stdio_.h" /* sprintf() for debug output */
22
23
#include "gserrors.h"
24
#include "gdebug.h"
25
#include "strimpl.h"
26
#include "sjbig2.h"
27
#include <limits.h>                     /* UINT_MAX */
28
29
/* stream implementation */
30
31
/* The /JBIG2Decode filter is a fairly memory intensive one to begin with,
32
   particularly in the initial jbig2dec library implementation. Furthermore,
33
   as a PDF 1.4 feature, we can assume a fairly large (host-level) machine.
34
   We therefore dispense with the normal Ghostscript memory discipline and
35
   let the library allocate all its resources on the heap. The pointers to
36
   these are not enumerated and so will not be garbage collected. We rely
37
   on our release() proc being called to deallocate state.
38
 */
39
40
private_st_jbig2decode_state(); /* creates a gc object for our state, defined in sjbig2.h */
41
42
/* error callback for jbig2 decoder */
43
static void
44
s_jbig2decode_error(void *callback_data, const char *msg, Jbig2Severity severity,
45
               uint32_t seg_idx)
46
902
{
47
902
    s_jbig2_callback_data_t *error_data = (s_jbig2_callback_data_t *)callback_data;
48
902
    const char *type;
49
902
    char segment[22];
50
51
902
    switch (severity) {
52
534
        case JBIG2_SEVERITY_DEBUG:
53
534
            type = "DEBUG"; break;;
54
342
        case JBIG2_SEVERITY_INFO:
55
342
            type = "info"; break;;
56
24
        case JBIG2_SEVERITY_WARNING:
57
24
            type = "WARNING"; break;;
58
2
        case JBIG2_SEVERITY_FATAL:
59
2
            type = "FATAL ERROR decoding image:";
60
            /* pass the fatal error upstream if possible */
61
2
            if (error_data != NULL) error_data->error = gs_error_ioerror;
62
2
            break;;
63
0
        default: type = "unknown message:"; break;;
64
902
    }
65
902
    if (seg_idx == JBIG2_UNKNOWN_SEGMENT_NUMBER) segment[0] = '\0';
66
776
    else gs_snprintf(segment, sizeof(segment), "(segment 0x%02x)", seg_idx);
67
68
902
    if (error_data)
69
902
    {
70
902
        char *message;
71
902
        int len;
72
73
902
        len = snprintf(NULL, 0, "jbig2dec %s %s %s", type, msg, segment);
74
902
        if (len < 0)
75
0
            return;
76
77
902
        message = (char *)gs_alloc_bytes(error_data->memory, len + 1, "sjbig2decode_error(message)");
78
902
        if (message == NULL)
79
0
            return;
80
81
902
        len = snprintf(message, len + 1, "jbig2dec %s %s %s", type, msg, segment);
82
902
        if (len < 0)
83
0
        {
84
0
            gs_free_object(error_data->memory, message, "s_jbig2decode_error(message)");
85
0
            return;
86
0
        }
87
88
902
        if (error_data->last_message != NULL && strcmp(message, error_data->last_message)) {
89
832
            if (error_data->repeats > 1)
90
2
            {
91
2
                if (error_data->severity == JBIG2_SEVERITY_FATAL || error_data->severity == JBIG2_SEVERITY_WARNING) {
92
2
                    dmlprintf1(error_data->memory, "jbig2dec last message repeated %ld times\n", error_data->repeats);
93
2
                } else {
94
0
                    if_debug1m('w', error_data->memory, "[w] jbig2dec last message repeated %ld times\n", error_data->repeats);
95
0
                }
96
2
            }
97
832
            gs_free_object(error_data->memory, error_data->last_message, "s_jbig2decode_error(last_message)");
98
832
            if (severity == JBIG2_SEVERITY_FATAL || severity == JBIG2_SEVERITY_WARNING) {
99
18
                dmlprintf1(error_data->memory, "%s\n", message);
100
814
            } else {
101
814
                if_debug1m('w', error_data->memory, "[w] %s\n", message);
102
814
            }
103
832
            error_data->last_message = message;
104
832
            error_data->severity = severity;
105
832
            error_data->type = type;
106
832
            error_data->repeats = 0;
107
832
        }
108
70
        else if (error_data->last_message != NULL) {
109
9
            error_data->repeats++;
110
9
            if (error_data->repeats % 1000000 == 0)
111
0
            {
112
0
                if (error_data->severity == JBIG2_SEVERITY_FATAL || error_data->severity == JBIG2_SEVERITY_WARNING) {
113
0
                    dmlprintf1(error_data->memory, "jbig2dec last message repeated %ld times so far\n", error_data->repeats);
114
0
                } else {
115
0
                    if_debug1m('w', error_data->memory, "[w] jbig2dec last message repeated %ld times so far\n", error_data->repeats);
116
0
                }
117
0
            }
118
9
            gs_free_object(error_data->memory, message, "s_jbig2decode_error(message)");
119
9
        }
120
61
        else if (error_data->last_message == NULL) {
121
61
            if (severity == JBIG2_SEVERITY_FATAL || severity == JBIG2_SEVERITY_WARNING) {
122
0
                dmlprintf1(error_data->memory, "%s\n", message);
123
61
            } else {
124
61
                if_debug1m('w', error_data->memory, "[w] %s\n", message);
125
61
            }
126
61
            error_data->last_message = message;
127
61
            error_data->severity = severity;
128
61
            error_data->type = type;
129
61
            error_data->repeats = 0;
130
61
        }
131
902
    }
132
0
    else
133
0
    {
134
/*
135
        FIXME s_jbig2_callback_data_t should be updated so that jbig2_ctx_new is not called
136
        with a NULL argument (see jbig2.h) and we never reach here with a NULL state
137
*/
138
0
        if (severity == JBIG2_SEVERITY_FATAL) {
139
0
            dlprintf3("jbig2dec %s %s %s\n", type, msg, segment);
140
0
        } else {
141
0
            if_debug3('w', "[w] jbig2dec %s %s %s\n", type, msg, segment);
142
0
        }
143
0
    }
144
902
}
145
146
static void
147
s_jbig2decode_flush_errors(void *callback_data)
148
64
{
149
64
    s_jbig2_callback_data_t *error_data = (s_jbig2_callback_data_t *)callback_data;
150
151
64
    if (error_data == NULL)
152
0
        return;
153
154
64
    if (error_data->last_message != NULL) {
155
61
        if (error_data->repeats > 1)
156
0
        {
157
0
            if (error_data->severity == JBIG2_SEVERITY_FATAL || error_data->severity == JBIG2_SEVERITY_WARNING) {
158
0
                dmlprintf1(error_data->memory, "jbig2dec last message repeated %ld times\n", error_data->repeats);
159
0
            } else {
160
0
                if_debug1m('w', error_data->memory, "[w] jbig2dec last message repeated %ld times\n", error_data->repeats);
161
0
            }
162
0
        }
163
61
        gs_free_object(error_data->memory, error_data->last_message, "s_jbig2decode_error(last_message)");
164
61
        error_data->last_message = NULL;
165
61
        error_data->repeats = 0;
166
61
    }
167
64
}
168
169
/* invert the bits in a buffer */
170
/* jbig2 and postscript have different senses of what pixel
171
   value is black, so we must invert the image */
172
static void
173
s_jbig2decode_invert_buffer(unsigned char *buf, size_t length)
174
24.4k
{
175
24.4k
    size_t i;
176
177
50.0M
    for (i = 0; i < length; i++)
178
49.9M
        *buf++ ^= 0xFF;
179
24.4k
}
180
181
typedef struct {
182
        Jbig2Allocator allocator;
183
        gs_memory_t *mem;
184
} s_jbig2decode_allocator_t;
185
186
static void *s_jbig2decode_alloc(Jbig2Allocator *_allocator, size_t size)
187
1.44k
{
188
1.44k
        s_jbig2decode_allocator_t *allocator = (s_jbig2decode_allocator_t *) _allocator;
189
1.44k
        if (size > UINT_MAX)
190
0
            return NULL;
191
1.44k
        return gs_alloc_bytes(allocator->mem, size, "s_jbig2decode_alloc");
192
1.44k
}
193
194
static void s_jbig2decode_free(Jbig2Allocator *_allocator, void *p)
195
1.65k
{
196
1.65k
        s_jbig2decode_allocator_t *allocator = (s_jbig2decode_allocator_t *) _allocator;
197
1.65k
        gs_free_object(allocator->mem, p, "s_jbig2decode_free");
198
1.65k
}
199
200
static void *s_jbig2decode_realloc(Jbig2Allocator *_allocator, void *p, size_t size)
201
0
{
202
0
        s_jbig2decode_allocator_t *allocator = (s_jbig2decode_allocator_t *) _allocator;
203
0
        if (size > UINT_MAX)
204
0
            return NULL;
205
0
        return gs_resize_object(allocator->mem, p, size, "s_jbig2decode_realloc");
206
0
}
207
208
/* parse a globals stream packed into a gs_bytestring for us by the postscript
209
   layer and stuff the resulting context into a pointer for use in later decoding */
210
int
211
s_jbig2decode_make_global_data(gs_memory_t *mem, byte *data, uint length, void **result)
212
0
{
213
0
    Jbig2Ctx *ctx = NULL;
214
0
    int code;
215
0
    s_jbig2decode_allocator_t *allocator;
216
217
    /* the cvision encoder likes to include empty global streams */
218
0
    if (length == 0) {
219
0
        if_debug0('w', "[w] ignoring zero-length jbig2 global stream.\n");
220
0
        *result = NULL;
221
0
        return 0;
222
0
    }
223
224
0
    allocator = (s_jbig2decode_allocator_t *) gs_alloc_bytes(mem,
225
0
            sizeof (s_jbig2decode_allocator_t), "s_jbig2_make_global_data");
226
0
    if (allocator == NULL) {
227
0
        *result = NULL;
228
0
        return_error(gs_error_VMerror);
229
0
    }
230
231
0
    allocator->allocator.alloc = s_jbig2decode_alloc;
232
0
    allocator->allocator.free = s_jbig2decode_free;
233
0
    allocator->allocator.realloc = s_jbig2decode_realloc;
234
0
    allocator->mem = mem;
235
236
    /* allocate a context with which to parse our global segments */
237
0
    ctx = jbig2_ctx_new((Jbig2Allocator *) allocator, JBIG2_OPTIONS_EMBEDDED,
238
0
                            NULL, s_jbig2decode_error, NULL);
239
0
    if (ctx == NULL) {
240
0
        gs_free_object(mem, allocator, "s_jbig2_make_global_data");
241
0
        return_error(gs_error_VMerror);
242
0
    }
243
244
    /* parse the global bitstream */
245
0
    code = jbig2_data_in(ctx, data, length);
246
0
    if (code) {
247
        /* error parsing the global stream */
248
0
        allocator = (s_jbig2decode_allocator_t *) jbig2_ctx_free(ctx);
249
0
        gs_free_object(allocator->mem, allocator, "s_jbig2_make_global_data");
250
0
        *result = NULL;
251
0
        return_error(gs_error_ioerror);
252
0
    }
253
254
    /* canonize and store our global state */
255
0
    *result = jbig2_make_global_ctx(ctx);
256
257
0
    return 0; /* todo: check for allocation failure */
258
0
}
259
260
/* release a global ctx pointer */
261
void
262
s_jbig2decode_free_global_data(void *data)
263
0
{
264
0
    Jbig2GlobalCtx *global_ctx = (Jbig2GlobalCtx*)data;
265
0
    s_jbig2decode_allocator_t *allocator;
266
267
0
    allocator = (s_jbig2decode_allocator_t *) jbig2_global_ctx_free(global_ctx);
268
269
0
    gs_free_object(allocator->mem, allocator, "s_jbig2decode_free_global_data");
270
0
}
271
272
/* store a global ctx pointer in our state structure.
273
 * If "gd" is NULL, then this library must free the global context.
274
 * If not-NULL, then it will be memory managed by caller, for example,
275
 * garbage collected in the case of the PS interpreter.
276
 * Currently gpdf will use NULL, and the PDF implemented in the gs interpreter would use
277
 * the garbage collection.
278
 */
279
int
280
s_jbig2decode_set_global_data(stream_state *ss, s_jbig2_global_data_t *gd, void *global_ctx)
281
64
{
282
64
    stream_jbig2decode_state *state = (stream_jbig2decode_state*)ss;
283
64
    state->global_struct = gd;
284
64
    state->global_ctx = global_ctx;
285
64
    return 0;
286
64
}
287
288
/* initialize the steam.
289
   this involves allocating the context structures, and
290
   initializing the global context from the /JBIG2Globals object reference
291
 */
292
static int
293
s_jbig2decode_init(stream_state * ss)
294
64
{
295
64
    stream_jbig2decode_state *const state = (stream_jbig2decode_state *) ss;
296
64
    Jbig2GlobalCtx *global_ctx = state->global_ctx; /* may be NULL */
297
64
    int code = 0;
298
64
    s_jbig2decode_allocator_t *allocator = NULL;
299
300
64
    state->callback_data = (s_jbig2_callback_data_t *)gs_alloc_bytes(
301
64
                                                ss->memory->non_gc_memory,
302
64
                                                sizeof(s_jbig2_callback_data_t),
303
64
            "s_jbig2decode_init(callback_data)");
304
64
    if (state->callback_data) {
305
64
        state->callback_data->memory = ss->memory->non_gc_memory;
306
64
        state->callback_data->error = 0;
307
64
        state->callback_data->last_message = NULL;
308
64
        state->callback_data->repeats = 0;
309
310
64
        allocator = (s_jbig2decode_allocator_t *) gs_alloc_bytes(ss->memory->non_gc_memory, sizeof (s_jbig2decode_allocator_t), "s_jbig2decode_init(allocator)");
311
64
        if (allocator == NULL) {
312
0
                s_jbig2decode_error(state->callback_data, "failed to allocate custom jbig2dec allocator", JBIG2_SEVERITY_FATAL, -1);
313
0
        }
314
64
        else {
315
64
                allocator->allocator.alloc = s_jbig2decode_alloc;
316
64
                allocator->allocator.free = s_jbig2decode_free;
317
64
                allocator->allocator.realloc = s_jbig2decode_realloc;
318
64
                allocator->mem = ss->memory->non_gc_memory;
319
320
                /* initialize the decoder with the parsed global context if any */
321
64
                state->decode_ctx = jbig2_ctx_new((Jbig2Allocator *) allocator, JBIG2_OPTIONS_EMBEDDED,
322
64
                             global_ctx, s_jbig2decode_error, state->callback_data);
323
324
64
                if (state->decode_ctx == NULL) {
325
0
                        gs_free_object(allocator->mem, allocator, "s_jbig2decode_release");
326
0
                }
327
328
64
        }
329
330
64
        code = state->callback_data->error;
331
64
    }
332
0
    else {
333
0
        code = gs_error_VMerror;
334
0
    }
335
64
    state->image = 0;
336
337
338
64
    return_error (code);
339
64
}
340
341
/* process a section of the input and return any decoded data.
342
   see strimpl.h for return codes.
343
 */
344
static int
345
s_jbig2decode_process(stream_state * ss, stream_cursor_read * pr,
346
                  stream_cursor_write * pw, bool last)
347
25.0k
{
348
25.0k
    stream_jbig2decode_state *const state = (stream_jbig2decode_state *) ss;
349
25.0k
    Jbig2Image *image = state->image;
350
25.0k
    size_t in_size = pr->limit - pr->ptr;
351
25.0k
    size_t out_size = pw->limit - pw->ptr;
352
25.0k
    int status = 0;
353
354
    /* there will only be a single page image,
355
       so pass all data in before looking for any output.
356
       note that the gs stream library expects offset-by-one
357
       indexing of the buffers, while jbig2dec uses normal 0 indexes */
358
25.0k
    if (in_size > 0) {
359
        /* pass all available input to the decoder */
360
564
        jbig2_data_in(state->decode_ctx, pr->ptr + 1, in_size);
361
564
        pr->ptr += in_size;
362
        /* simulate end-of-page segment */
363
564
        if (last == 1) {
364
60
            jbig2_complete_page(state->decode_ctx);
365
60
        }
366
        /* handle fatal decoding errors reported through our callback */
367
564
        if (state->callback_data->error) return state->callback_data->error;
368
564
    }
369
25.0k
    if (out_size > 0) {
370
25.0k
        if (image == NULL) {
371
            /* see if a page image in available */
372
623
            image = jbig2_page_out(state->decode_ctx);
373
623
            if (image != NULL) {
374
59
                state->image = image;
375
59
                state->offset = 0;
376
59
            }
377
623
        }
378
25.0k
        if (image != NULL) {
379
            /* copy data out of the decoded image, if any */
380
24.4k
            size_t image_size = (size_t)image->height*image->stride;
381
24.4k
            size_t usable = min(image_size - state->offset, out_size);
382
24.4k
            memcpy(pw->ptr + 1, image->data + state->offset, usable);
383
24.4k
            s_jbig2decode_invert_buffer(pw->ptr + 1, usable);
384
24.4k
            state->offset += usable;
385
24.4k
            pw->ptr += usable;
386
24.4k
            status = (state->offset < image_size) ? 1 : 0;
387
24.4k
        }
388
25.0k
    }
389
390
25.0k
    return status;
391
25.0k
}
392
393
/* stream release.
394
   free all our decoder state.
395
 */
396
static void
397
s_jbig2decode_release(stream_state *ss)
398
128
{
399
128
    stream_jbig2decode_state *const state = (stream_jbig2decode_state *) ss;
400
401
128
    if (state->decode_ctx) {
402
64
        s_jbig2decode_allocator_t *allocator = NULL;
403
404
64
        if (state->image) jbig2_release_page(state->decode_ctx, state->image);
405
64
  state->image = NULL;
406
64
        s_jbig2decode_flush_errors(state->callback_data);
407
64
        allocator = (s_jbig2decode_allocator_t *) jbig2_ctx_free(state->decode_ctx);
408
64
  state->decode_ctx = NULL;
409
410
64
        gs_free_object(allocator->mem, allocator, "s_jbig2decode_release");
411
64
    }
412
128
    if (state->callback_data) {
413
64
        gs_memory_t *mem = state->callback_data->memory;
414
64
        gs_free_object(state->callback_data->memory, state->callback_data->last_message, "s_jbig2decode_release(message)");
415
64
        gs_free_object(mem, state->callback_data, "s_jbig2decode_release(callback_data)");
416
64
  state->callback_data = NULL;
417
64
    }
418
128
    if (state->global_struct != NULL) {
419
        /* the interpreter calls jbig2decode_free_global_data() separately */
420
128
    } else {
421
        /* We are responsible for freeing global context */
422
128
        if (state->global_ctx) {
423
0
            s_jbig2decode_free_global_data(state->global_ctx);
424
0
            state->global_ctx = NULL;
425
0
        }
426
128
    }
427
128
}
428
429
void
430
s_jbig2decode_finalize(const gs_memory_t *cmem, void *vptr)
431
64
{
432
64
    (void)cmem;
433
434
64
    s_jbig2decode_release((stream_state *)vptr);
435
64
}
436
437
/* set stream defaults.
438
   this hook exists to avoid confusing the gc with bogus
439
   pointers. we use it similarly just to NULL all the pointers.
440
   (could just be done in _init?)
441
 */
442
static void
443
s_jbig2decode_set_defaults(stream_state *ss)
444
0
{
445
0
    stream_jbig2decode_state *const state = (stream_jbig2decode_state *) ss;
446
447
    /* state->global_ctx is not owned by us */
448
0
    state->global_struct = NULL;
449
0
    state->global_ctx = NULL;
450
0
    state->decode_ctx = NULL;
451
0
    state->image = NULL;
452
0
    state->offset = 0;
453
0
    state->callback_data = NULL;
454
0
}
455
456
/* stream template */
457
const stream_template s_jbig2decode_template = {
458
    &st_jbig2decode_state,
459
    s_jbig2decode_init,
460
    s_jbig2decode_process,
461
    1, 1, /* min in and out buffer sizes we can handle --should be ~32k,64k for efficiency? */
462
    s_jbig2decode_release,
463
    s_jbig2decode_set_defaults
464
};