1 /* Copyright (C) 2001-2019 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
s_jbig2decode_error(void * callback_data,const char * msg,Jbig2Severity severity,int32_t seg_idx)44 s_jbig2decode_error(void *callback_data, const char *msg, Jbig2Severity severity,
45 int32_t seg_idx)
46 {
47 s_jbig2_callback_data_t *error_data = (s_jbig2_callback_data_t *)callback_data;
48 const char *type;
49 char segment[22];
50
51 switch (severity) {
52 case JBIG2_SEVERITY_DEBUG:
53 type = "DEBUG"; break;;
54 case JBIG2_SEVERITY_INFO:
55 type = "info"; break;;
56 case JBIG2_SEVERITY_WARNING:
57 type = "WARNING"; break;;
58 case JBIG2_SEVERITY_FATAL:
59 type = "FATAL ERROR decoding image:";
60 /* pass the fatal error upstream if possible */
61 if (error_data != NULL) error_data->error = gs_error_ioerror;
62 break;;
63 default: type = "unknown message:"; break;;
64 }
65 if (seg_idx == -1) segment[0] = '\0';
66 else gs_sprintf(segment, "(segment 0x%02x)", seg_idx);
67
68 if (error_data)
69 {
70 char *message;
71 int len;
72
73 len = snprintf(NULL, 0, "jbig2dec %s %s %s", type, msg, segment);
74 if (len < 0)
75 return;
76
77 message = (char *)gs_alloc_bytes(error_data->memory, len + 1, "sjbig2decode_error(message)");
78 if (message == NULL)
79 return;
80
81 len = snprintf(message, len + 1, "jbig2dec %s %s %s", type, msg, segment);
82 if (len < 0)
83 {
84 gs_free_object(error_data->memory, message, "s_jbig2decode_error(message)");
85 return;
86 }
87
88 if (error_data->last_message != NULL && strcmp(message, error_data->last_message)) {
89 if (error_data->repeats > 1)
90 {
91 if (error_data->severity == JBIG2_SEVERITY_FATAL || error_data->severity == JBIG2_SEVERITY_WARNING) {
92 dmlprintf1(error_data->memory, "jbig2dec last message repeated %ld times\n", error_data->repeats);
93 } else {
94 if_debug1m('w', error_data->memory, "[w] jbig2dec last message repeated %ld times\n", error_data->repeats);
95 }
96 }
97 gs_free_object(error_data->memory, error_data->last_message, "s_jbig2decode_error(last_message)");
98 if (severity == JBIG2_SEVERITY_FATAL || severity == JBIG2_SEVERITY_WARNING) {
99 dmlprintf1(error_data->memory, "%s\n", message);
100 } else {
101 if_debug1m('w', error_data->memory, "[w] %s\n", message);
102 }
103 error_data->last_message = message;
104 error_data->severity = severity;
105 error_data->type = type;
106 error_data->repeats = 0;
107 }
108 else if (error_data->last_message != NULL) {
109 error_data->repeats++;
110 if (error_data->repeats % 1000000 == 0)
111 {
112 if (error_data->severity == JBIG2_SEVERITY_FATAL || error_data->severity == JBIG2_SEVERITY_WARNING) {
113 dmlprintf1(error_data->memory, "jbig2dec last message repeated %ld times so far\n", error_data->repeats);
114 } else {
115 if_debug1m('w', error_data->memory, "[w] jbig2dec last message repeated %ld times so far\n", error_data->repeats);
116 }
117 }
118 gs_free_object(error_data->memory, message, "s_jbig2decode_error(message)");
119 }
120 else if (error_data->last_message == NULL) {
121 if (severity == JBIG2_SEVERITY_FATAL || severity == JBIG2_SEVERITY_WARNING) {
122 dmlprintf1(error_data->memory, "%s\n", message);
123 } else {
124 if_debug1m('w', error_data->memory, "[w] %s\n", message);
125 }
126 error_data->last_message = message;
127 error_data->severity = severity;
128 error_data->type = type;
129 error_data->repeats = 0;
130 }
131 }
132 else
133 {
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 if (severity == JBIG2_SEVERITY_FATAL) {
139 dlprintf3("jbig2dec %s %s %s\n", type, msg, segment);
140 } else {
141 if_debug3('w', "[w] jbig2dec %s %s %s\n", type, msg, segment);
142 }
143 }
144 }
145
146 static void
s_jbig2decode_flush_errors(void * callback_data)147 s_jbig2decode_flush_errors(void *callback_data)
148 {
149 s_jbig2_callback_data_t *error_data = (s_jbig2_callback_data_t *)callback_data;
150
151 if (error_data == NULL)
152 return;
153
154 if (error_data->last_message != NULL) {
155 if (error_data->repeats > 1)
156 {
157 if (error_data->severity == JBIG2_SEVERITY_FATAL || error_data->severity == JBIG2_SEVERITY_WARNING) {
158 dmlprintf1(error_data->memory, "jbig2dec last message repeated %ld times\n", error_data->repeats);
159 } else {
160 if_debug1m('w', error_data->memory, "[w] jbig2dec last message repeated %ld times\n", error_data->repeats);
161 }
162 }
163 gs_free_object(error_data->memory, error_data->last_message, "s_jbig2decode_error(last_message)");
164 error_data->last_message = NULL;
165 error_data->repeats = 0;
166 }
167 }
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
s_jbig2decode_invert_buffer(unsigned char * buf,int length)173 s_jbig2decode_invert_buffer(unsigned char *buf, int length)
174 {
175 int i;
176
177 for (i = 0; i < length; i++)
178 *buf++ ^= 0xFF;
179 }
180
181 typedef struct {
182 Jbig2Allocator allocator;
183 gs_memory_t *mem;
184 } s_jbig2decode_allocator_t;
185
s_jbig2decode_alloc(Jbig2Allocator * _allocator,size_t size)186 static void *s_jbig2decode_alloc(Jbig2Allocator *_allocator, size_t size)
187 {
188 s_jbig2decode_allocator_t *allocator = (s_jbig2decode_allocator_t *) _allocator;
189 if (size > UINT_MAX)
190 return NULL;
191 return gs_alloc_bytes(allocator->mem, size, "s_jbig2decode_alloc");
192 }
193
s_jbig2decode_free(Jbig2Allocator * _allocator,void * p)194 static void s_jbig2decode_free(Jbig2Allocator *_allocator, void *p)
195 {
196 s_jbig2decode_allocator_t *allocator = (s_jbig2decode_allocator_t *) _allocator;
197 gs_free_object(allocator->mem, p, "s_jbig2decode_free");
198 }
199
s_jbig2decode_realloc(Jbig2Allocator * _allocator,void * p,size_t size)200 static void *s_jbig2decode_realloc(Jbig2Allocator *_allocator, void *p, size_t size)
201 {
202 s_jbig2decode_allocator_t *allocator = (s_jbig2decode_allocator_t *) _allocator;
203 if (size > UINT_MAX)
204 return NULL;
205 return gs_resize_object(allocator->mem, p, size, "s_jbig2decode_realloc");
206 }
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
s_jbig2decode_make_global_data(gs_memory_t * mem,byte * data,uint length,void ** result)211 s_jbig2decode_make_global_data(gs_memory_t *mem, byte *data, uint length, void **result)
212 {
213 Jbig2Ctx *ctx = NULL;
214 int code;
215 s_jbig2decode_allocator_t *allocator;
216
217 /* the cvision encoder likes to include empty global streams */
218 if (length == 0) {
219 if_debug0('w', "[w] ignoring zero-length jbig2 global stream.\n");
220 *result = NULL;
221 return 0;
222 }
223
224 allocator = (s_jbig2decode_allocator_t *) gs_alloc_bytes(mem,
225 sizeof (s_jbig2decode_allocator_t), "s_jbig2_make_global_data");
226 if (allocator == NULL) {
227 *result = NULL;
228 return_error(gs_error_VMerror);
229 }
230
231 allocator->allocator.alloc = s_jbig2decode_alloc;
232 allocator->allocator.free = s_jbig2decode_free;
233 allocator->allocator.realloc = s_jbig2decode_realloc;
234 allocator->mem = mem;
235
236 /* allocate a context with which to parse our global segments */
237 ctx = jbig2_ctx_new((Jbig2Allocator *) allocator, JBIG2_OPTIONS_EMBEDDED,
238 NULL, s_jbig2decode_error, NULL);
239 if (ctx == NULL) {
240 gs_free_object(mem, allocator, "s_jbig2_make_global_data");
241 return_error(gs_error_VMerror);
242 }
243
244 /* parse the global bitstream */
245 code = jbig2_data_in(ctx, data, length);
246 if (code) {
247 /* error parsing the global stream */
248 allocator = (s_jbig2decode_allocator_t *) jbig2_ctx_free(ctx);
249 gs_free_object(allocator->mem, allocator, "s_jbig2_make_global_data");
250 *result = NULL;
251 return_error(gs_error_ioerror);
252 }
253
254 /* canonize and store our global state */
255 *result = jbig2_make_global_ctx(ctx);
256
257 return 0; /* todo: check for allocation failure */
258 }
259
260 /* release a global ctx pointer */
261 void
s_jbig2decode_free_global_data(void * data)262 s_jbig2decode_free_global_data(void *data)
263 {
264 Jbig2GlobalCtx *global_ctx = (Jbig2GlobalCtx*)data;
265 s_jbig2decode_allocator_t *allocator;
266
267 allocator = (s_jbig2decode_allocator_t *) jbig2_global_ctx_free(global_ctx);
268
269 gs_free_object(allocator->mem, allocator, "s_jbig2decode_free_global_data");
270 }
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
s_jbig2decode_set_global_data(stream_state * ss,s_jbig2_global_data_t * gd,void * global_ctx)280 s_jbig2decode_set_global_data(stream_state *ss, s_jbig2_global_data_t *gd, void *global_ctx)
281 {
282 stream_jbig2decode_state *state = (stream_jbig2decode_state*)ss;
283 state->global_struct = gd;
284 state->global_ctx = global_ctx;
285 return 0;
286 }
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
s_jbig2decode_init(stream_state * ss)293 s_jbig2decode_init(stream_state * ss)
294 {
295 stream_jbig2decode_state *const state = (stream_jbig2decode_state *) ss;
296 Jbig2GlobalCtx *global_ctx = state->global_ctx; /* may be NULL */
297 int code = 0;
298 s_jbig2decode_allocator_t *allocator = NULL;
299
300 state->callback_data = (s_jbig2_callback_data_t *)gs_alloc_bytes(
301 ss->memory->non_gc_memory,
302 sizeof(s_jbig2_callback_data_t),
303 "s_jbig2decode_init(callback_data)");
304 if (state->callback_data) {
305 state->callback_data->memory = ss->memory->non_gc_memory;
306 state->callback_data->error = 0;
307 state->callback_data->last_message = NULL;
308 state->callback_data->repeats = 0;
309
310 allocator = (s_jbig2decode_allocator_t *) gs_alloc_bytes(ss->memory->non_gc_memory, sizeof (s_jbig2decode_allocator_t), "s_jbig2decode_init(allocator)");
311 if (allocator == NULL) {
312 s_jbig2decode_error(state->callback_data, "failed to allocate custom jbig2dec allocator", JBIG2_SEVERITY_FATAL, -1);
313 }
314 else {
315 allocator->allocator.alloc = s_jbig2decode_alloc;
316 allocator->allocator.free = s_jbig2decode_free;
317 allocator->allocator.realloc = s_jbig2decode_realloc;
318 allocator->mem = ss->memory->non_gc_memory;
319
320 /* initialize the decoder with the parsed global context if any */
321 state->decode_ctx = jbig2_ctx_new((Jbig2Allocator *) allocator, JBIG2_OPTIONS_EMBEDDED,
322 global_ctx, s_jbig2decode_error, state->callback_data);
323
324 if (state->decode_ctx == NULL) {
325 gs_free_object(allocator->mem, allocator, "s_jbig2decode_release");
326 }
327
328 }
329
330 code = state->callback_data->error;
331 }
332 else {
333 code = gs_error_VMerror;
334 }
335 state->image = 0;
336
337
338 return_error (code);
339 }
340
341 /* process a section of the input and return any decoded data.
342 see strimpl.h for return codes.
343 */
344 static int
s_jbig2decode_process(stream_state * ss,stream_cursor_read * pr,stream_cursor_write * pw,bool last)345 s_jbig2decode_process(stream_state * ss, stream_cursor_read * pr,
346 stream_cursor_write * pw, bool last)
347 {
348 stream_jbig2decode_state *const state = (stream_jbig2decode_state *) ss;
349 Jbig2Image *image = state->image;
350 long in_size = pr->limit - pr->ptr;
351 long out_size = pw->limit - pw->ptr;
352 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 if (in_size > 0) {
359 /* pass all available input to the decoder */
360 jbig2_data_in(state->decode_ctx, pr->ptr + 1, in_size);
361 pr->ptr += in_size;
362 /* simulate end-of-page segment */
363 if (last == 1) {
364 jbig2_complete_page(state->decode_ctx);
365 }
366 /* handle fatal decoding errors reported through our callback */
367 if (state->callback_data->error) return state->callback_data->error;
368 }
369 if (out_size > 0) {
370 if (image == NULL) {
371 /* see if a page image in available */
372 image = jbig2_page_out(state->decode_ctx);
373 if (image != NULL) {
374 state->image = image;
375 state->offset = 0;
376 }
377 }
378 if (image != NULL) {
379 /* copy data out of the decoded image, if any */
380 long image_size = image->height*image->stride;
381 long usable = min(image_size - state->offset, out_size);
382 memcpy(pw->ptr + 1, image->data + state->offset, usable);
383 s_jbig2decode_invert_buffer(pw->ptr + 1, usable);
384 state->offset += usable;
385 pw->ptr += usable;
386 status = (state->offset < image_size) ? 1 : 0;
387 }
388 }
389
390 return status;
391 }
392
393 /* stream release.
394 free all our decoder state.
395 */
396 static void
s_jbig2decode_release(stream_state * ss)397 s_jbig2decode_release(stream_state *ss)
398 {
399 stream_jbig2decode_state *const state = (stream_jbig2decode_state *) ss;
400
401 if (state->decode_ctx) {
402 s_jbig2decode_allocator_t *allocator = NULL;
403
404 if (state->image) jbig2_release_page(state->decode_ctx, state->image);
405 state->image = NULL;
406 s_jbig2decode_flush_errors(state->callback_data);
407 allocator = (s_jbig2decode_allocator_t *) jbig2_ctx_free(state->decode_ctx);
408 state->decode_ctx = NULL;
409
410 gs_free_object(allocator->mem, allocator, "s_jbig2decode_release");
411 }
412 if (state->callback_data) {
413 gs_memory_t *mem = state->callback_data->memory;
414 gs_free_object(state->callback_data->memory, state->callback_data->last_message, "s_jbig2decode_release(message)");
415 gs_free_object(mem, state->callback_data, "s_jbig2decode_release(callback_data)");
416 state->callback_data = NULL;
417 }
418 if (state->global_struct != NULL) {
419 /* the interpreter calls jbig2decode_free_global_data() separately */
420 } else {
421 /* We are responsible for freeing global context */
422 if (state->global_ctx) {
423 s_jbig2decode_free_global_data(state->global_ctx);
424 state->global_ctx = NULL;
425 }
426 }
427 }
428
429 void
s_jbig2decode_finalize(const gs_memory_t * cmem,void * vptr)430 s_jbig2decode_finalize(const gs_memory_t *cmem, void *vptr)
431 {
432 (void)cmem;
433
434 s_jbig2decode_release((stream_state *)vptr);
435 }
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
s_jbig2decode_set_defaults(stream_state * ss)443 s_jbig2decode_set_defaults(stream_state *ss)
444 {
445 stream_jbig2decode_state *const state = (stream_jbig2decode_state *) ss;
446
447 /* state->global_ctx is not owned by us */
448 state->global_struct = NULL;
449 state->global_ctx = NULL;
450 state->decode_ctx = NULL;
451 state->image = NULL;
452 state->offset = 0;
453 state->callback_data = NULL;
454 }
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 };
465