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 jbig2dec
18*/
19
20/* symbol dictionary segment decode and support */
21
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
25#include "os_types.h"
26
27#include <stddef.h>
28#include <string.h> /* memset() */
29
30#if defined(OUTPUT_PBM) || defined(DUMP_SYMDICT)
31#include <stdio.h>
32#endif
33
34#include "jbig2.h"
35#include "jbig2_priv.h"
36#include "jbig2_arith.h"
37#include "jbig2_arith_int.h"
38#include "jbig2_arith_iaid.h"
39#include "jbig2_generic.h"
40#include "jbig2_huffman.h"
41#include "jbig2_image.h"
42#include "jbig2_mmr.h"
43#include "jbig2_refinement.h"
44#include "jbig2_segment.h"
45#include "jbig2_symbol_dict.h"
46#include "jbig2_text.h"
47
48/* Table 13 */
49typedef struct {
50 bool SDHUFF;
51 bool SDREFAGG;
52 uint32_t SDNUMINSYMS;
53 Jbig2SymbolDict *SDINSYMS;
54 uint32_t SDNUMNEWSYMS;
55 uint32_t SDNUMEXSYMS;
56 Jbig2HuffmanTable *SDHUFFDH;
57 Jbig2HuffmanTable *SDHUFFDW;
58 Jbig2HuffmanTable *SDHUFFBMSIZE;
59 Jbig2HuffmanTable *SDHUFFAGGINST;
60 int SDTEMPLATE;
61 int8_t sdat[8];
62 bool SDRTEMPLATE;
63 int8_t sdrat[4];
64} Jbig2SymbolDictParams;
65
66/* Utility routines */
67
68#ifdef DUMP_SYMDICT
69void
70jbig2_dump_symbol_dict(Jbig2Ctx *ctx, Jbig2Segment *segment)
71{
72 Jbig2SymbolDict *dict = (Jbig2SymbolDict *) segment->result;
73 int index;
74 char filename[24];
75 int code;
76
77 if (dict == NULL)
78 return;
79 jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "dumping symbol dictionary as %d individual png files", dict->n_symbols);
80 for (index = 0; index < dict->n_symbols; index++) {
81 snprintf(filename, sizeof(filename), "symbol_%02d-%04d.png", segment->number, index);
82 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "dumping symbol %d/%d as '%s'", index, dict->n_symbols, filename);
83#ifdef HAVE_LIBPNG
84 code = jbig2_image_write_png_file(dict->glyphs[index], filename);
85#else
86 code = jbig2_image_write_pbm_file(dict->glyphs[index], filename);
87#endif
88 if (code < 0)
89 return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to dump symbol %d/%d as '%s'", index, dict->n_symbols, filename);
90 }
91}
92#endif /* DUMP_SYMDICT */
93
94/* return a new empty symbol dict */
95Jbig2SymbolDict *
96jbig2_sd_new(Jbig2Ctx *ctx, uint32_t n_symbols)
97{
98 Jbig2SymbolDict *new_dict = NULL;
99
100 new_dict = jbig2_new(ctx, Jbig2SymbolDict, 1);
101 if (new_dict != NULL) {
102 new_dict->glyphs = jbig2_new(ctx, Jbig2Image *, n_symbols);
103 new_dict->n_symbols = n_symbols;
104 } else {
105 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to allocate new empty symbol dictionary");
106 return NULL;
107 }
108
109 if (new_dict->glyphs != NULL) {
110 memset(new_dict->glyphs, 0, n_symbols * sizeof(Jbig2Image *));
111 } else if (new_dict->n_symbols > 0) {
112 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to allocate glyphs for new empty symbol dictionary");
113 jbig2_free(ctx->allocator, new_dict);
114 return NULL;
115 }
116
117 return new_dict;
118}
119
120/* release the memory associated with a symbol dict */
121void
122jbig2_sd_release(Jbig2Ctx *ctx, Jbig2SymbolDict *dict)
123{
124 uint32_t i;
125
126 if (dict == NULL)
127 return;
128 if (dict->glyphs != NULL)
129 for (i = 0; i < dict->n_symbols; i++)
130 jbig2_image_release(ctx, dict->glyphs[i]);
131 jbig2_free(ctx->allocator, dict->glyphs);
132 jbig2_free(ctx->allocator, dict);
133}
134
135/* get a particular glyph by index */
136Jbig2Image *
137jbig2_sd_glyph(Jbig2SymbolDict *dict, unsigned int id)
138{
139 if (dict == NULL)
140 return NULL;
141 return dict->glyphs[id];
142}
143
144/* count the number of dictionary segments referred to by the given segment */
145uint32_t
146jbig2_sd_count_referred(Jbig2Ctx *ctx, Jbig2Segment *segment)
147{
148 int index;
149 Jbig2Segment *rsegment;
150 uint32_t n_dicts = 0;
151
152 for (index = 0; index < segment->referred_to_segment_count; index++) {
153 rsegment = jbig2_find_segment(ctx, segment->referred_to_segments[index]);
154 if (rsegment && ((rsegment->flags & 63) == 0) &&
155 rsegment->result && (((Jbig2SymbolDict *) rsegment->result)->n_symbols > 0) && ((*((Jbig2SymbolDict *) rsegment->result)->glyphs) != NULL))
156 n_dicts++;
157 }
158
159 return (n_dicts);
160}
161
162/* return an array of pointers to symbol dictionaries referred to by the given segment */
163Jbig2SymbolDict **
164jbig2_sd_list_referred(Jbig2Ctx *ctx, Jbig2Segment *segment)
165{
166 int index;
167 Jbig2Segment *rsegment;
168 Jbig2SymbolDict **dicts;
169 uint32_t n_dicts = jbig2_sd_count_referred(ctx, segment);
170 uint32_t dindex = 0;
171
172 dicts = jbig2_new(ctx, Jbig2SymbolDict *, n_dicts);
173 if (dicts == NULL) {
174 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate referred list of symbol dictionaries");
175 return NULL;
176 }
177
178 for (index = 0; index < segment->referred_to_segment_count; index++) {
179 rsegment = jbig2_find_segment(ctx, segment->referred_to_segments[index]);
180 if (rsegment && ((rsegment->flags & 63) == 0) && rsegment->result &&
181 (((Jbig2SymbolDict *) rsegment->result)->n_symbols > 0) && ((*((Jbig2SymbolDict *) rsegment->result)->glyphs) != NULL)) {
182 /* add this referred to symbol dictionary */
183 dicts[dindex++] = (Jbig2SymbolDict *) rsegment->result;
184 }
185 }
186
187 if (dindex != n_dicts) {
188 /* should never happen */
189 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "counted %d symbol dictionaries but built a list with %d.", n_dicts, dindex);
190 jbig2_free(ctx->allocator, dicts);
191 return NULL;
192 }
193
194 return (dicts);
195}
196
197/* generate a new symbol dictionary by concatenating a list of
198 existing dictionaries */
199Jbig2SymbolDict *
200jbig2_sd_cat(Jbig2Ctx *ctx, uint32_t n_dicts, Jbig2SymbolDict **dicts)
201{
202 uint32_t i, j, k, symbols;
203 Jbig2SymbolDict *new_dict = NULL;
204
205 /* count the imported symbols and allocate a new array */
206 symbols = 0;
207 for (i = 0; i < n_dicts; i++)
208 symbols += dicts[i]->n_symbols;
209
210 /* fill a new array with new references to glyph pointers */
211 new_dict = jbig2_sd_new(ctx, symbols);
212 if (new_dict != NULL) {
213 k = 0;
214 for (i = 0; i < n_dicts; i++)
215 for (j = 0; j < dicts[i]->n_symbols; j++)
216 new_dict->glyphs[k++] = jbig2_image_reference(ctx, dicts[i]->glyphs[j]);
217 } else {
218 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1, "failed to allocate new symbol dictionary");
219 }
220
221 return new_dict;
222}
223
224/* Decoding routines */
225
226/* 6.5 */
227static Jbig2SymbolDict *
228jbig2_decode_symbol_dict(Jbig2Ctx *ctx,
229 Jbig2Segment *segment,
230 const Jbig2SymbolDictParams *params, const byte *data, size_t size, Jbig2ArithCx *GB_stats, Jbig2ArithCx *GR_stats)
231{
232 Jbig2SymbolDict *SDNEWSYMS = NULL;
233 Jbig2SymbolDict *SDEXSYMS = NULL;
234 uint32_t HCHEIGHT;
235 uint32_t NSYMSDECODED;
236 uint32_t SYMWIDTH, TOTWIDTH;
237 uint32_t HCFIRSTSYM;
238 uint32_t *SDNEWSYMWIDTHS = NULL;
239 int SBSYMCODELEN = 0;
240 Jbig2WordStream *ws = NULL;
241 Jbig2HuffmanState *hs = NULL;
242 Jbig2ArithState *as = NULL;
243 Jbig2ArithIntCtx *IADH = NULL;
244 Jbig2ArithIntCtx *IADW = NULL;
245 Jbig2ArithIntCtx *IAEX = NULL;
246 Jbig2ArithIntCtx *IAAI = NULL;
247 int code = 0;
248 Jbig2SymbolDict **refagg_dicts = NULL;
249 uint32_t i;
250 Jbig2TextRegionParams tparams;
251 Jbig2Image *image = NULL;
252 Jbig2Image *glyph = NULL;
253 uint32_t emptyruns = 0;
254
255 memset(&tparams, 0, sizeof(tparams));
256
257 /* 6.5.5 (3) */
258 HCHEIGHT = 0;
259 NSYMSDECODED = 0;
260
261 ws = jbig2_word_stream_buf_new(ctx, data, size);
262 if (ws == NULL) {
263 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate word stream when decoding symbol dictionary");
264 return NULL;
265 }
266
267 as = jbig2_arith_new(ctx, ws);
268 if (as == NULL) {
269 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate arithmetic coding state when decoding symbol dictionary");
270 jbig2_word_stream_buf_free(ctx, ws);
271 return NULL;
272 }
273
274 if (params->SDHUFF) {
275 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "huffman coded symbol dictionary");
276 hs = jbig2_huffman_new(ctx, ws);
277 tparams.SBHUFFRDX = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O); /* Table B.15 */
278 tparams.SBHUFFRDY = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O); /* Table B.15 */
279 tparams.SBHUFFRSIZE = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_A); /* Table B.1 */
280 if (hs == NULL || tparams.SBHUFFRDX == NULL ||
281 tparams.SBHUFFRDY == NULL || tparams.SBHUFFRSIZE == NULL) {
282 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate for symbol bitmap");
283 goto cleanup;
284 }
285 if (!params->SDREFAGG) {
286 SDNEWSYMWIDTHS = jbig2_new(ctx, uint32_t, params->SDNUMNEWSYMS);
287 if (SDNEWSYMWIDTHS == NULL) {
288 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate symbol widths (%u)", params->SDNUMNEWSYMS);
289 goto cleanup;
290 }
291 } else {
292 tparams.SBHUFFFS = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_F); /* Table B.6 */
293 tparams.SBHUFFDS = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_H); /* Table B.8 */
294 tparams.SBHUFFDT = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_K); /* Table B.11 */
295 tparams.SBHUFFRDW = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O); /* Table B.15 */
296 tparams.SBHUFFRDH = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O); /* Table B.15 */
297 if (tparams.SBHUFFFS == NULL || tparams.SBHUFFDS == NULL ||
298 tparams.SBHUFFDT == NULL || tparams.SBHUFFRDW == NULL ||
299 tparams.SBHUFFRDH == NULL) {
300 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "out of memory creating text region huffman decoder entries");
301 goto cleanup;
302 }
303 }
304 } else {
305 IADH = jbig2_arith_int_ctx_new(ctx);
306 IADW = jbig2_arith_int_ctx_new(ctx);
307 IAEX = jbig2_arith_int_ctx_new(ctx);
308 IAAI = jbig2_arith_int_ctx_new(ctx);
309 if (IADH == NULL || IADW == NULL || IAEX == NULL || IAAI == NULL) {
310 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate symbol bitmap");
311 goto cleanup;
312 }
313 for (SBSYMCODELEN = 0; ((uint64_t) 1 << SBSYMCODELEN) < ((uint64_t) params->SDNUMINSYMS + params->SDNUMNEWSYMS); SBSYMCODELEN++);
314 tparams.IAID = jbig2_arith_iaid_ctx_new(ctx, SBSYMCODELEN);
315 tparams.IARDX = jbig2_arith_int_ctx_new(ctx);
316 tparams.IARDY = jbig2_arith_int_ctx_new(ctx);
317 if (tparams.IAID == NULL || tparams.IARDX == NULL ||
318 tparams.IARDY == NULL) {
319 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region arithmetic decoder contexts");
320 goto cleanup;
321 }
322 if (params->SDREFAGG) {
323 /* Values from Table 17, section 6.5.8.2 (2) */
324 tparams.IADT = jbig2_arith_int_ctx_new(ctx);
325 tparams.IAFS = jbig2_arith_int_ctx_new(ctx);
326 tparams.IADS = jbig2_arith_int_ctx_new(ctx);
327 tparams.IAIT = jbig2_arith_int_ctx_new(ctx);
328 /* Table 31 */
329 tparams.IARI = jbig2_arith_int_ctx_new(ctx);
330 tparams.IARDW = jbig2_arith_int_ctx_new(ctx);
331 tparams.IARDH = jbig2_arith_int_ctx_new(ctx);
332 if (tparams.IADT == NULL || tparams.IAFS == NULL ||
333 tparams.IADS == NULL || tparams.IAIT == NULL ||
334 tparams.IARI == NULL || tparams.IARDW == NULL ||
335 tparams.IARDH == NULL) {
336 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region arith decoder contexts");
337 }
338 }
339 }
340 tparams.SBHUFF = params->SDHUFF;
341 tparams.SBREFINE = 1;
342 tparams.SBSTRIPS = 1;
343 tparams.SBDEFPIXEL = 0;
344 tparams.SBCOMBOP = JBIG2_COMPOSE_OR;
345 tparams.TRANSPOSED = 0;
346 tparams.REFCORNER = JBIG2_CORNER_TOPLEFT;
347 tparams.SBDSOFFSET = 0;
348 tparams.SBRTEMPLATE = params->SDRTEMPLATE;
349
350 SDNEWSYMS = jbig2_sd_new(ctx, params->SDNUMNEWSYMS);
351 if (SDNEWSYMS == NULL) {
352 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate new symbols (%u)", params->SDNUMNEWSYMS);
353 goto cleanup;
354 }
355
356 refagg_dicts = jbig2_new(ctx, Jbig2SymbolDict *, 2);
357 if (refagg_dicts == NULL) {
358 code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "Out of memory allocating dictionary array");
359 goto cleanup;
360 }
361 refagg_dicts[0] = jbig2_sd_new(ctx, params->SDNUMINSYMS);
362 if (refagg_dicts[0] == NULL) {
363 code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "out of memory allocating symbol dictionary");
364 goto cleanup;
365 }
366 for (i = 0; i < params->SDNUMINSYMS; i++) {
367 refagg_dicts[0]->glyphs[i] = jbig2_image_reference(ctx, params->SDINSYMS->glyphs[i]);
368 }
369 refagg_dicts[1] = SDNEWSYMS;
370
371 /* 6.5.5 (4a) */
372 while (NSYMSDECODED < params->SDNUMNEWSYMS) {
373 int32_t HCDH, DW;
374
375 /* 6.5.6 */
376 if (params->SDHUFF) {
377 HCDH = jbig2_huffman_get(hs, params->SDHUFFDH, &code);
378 } else {
379 code = jbig2_arith_int_decode(ctx, IADH, as, &HCDH);
380 }
381 if (code < 0) {
382 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode height class delta");
383 goto cleanup;
384 }
385 if (code > 0) {
386 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "OOB decoding height class delta");
387 goto cleanup;
388 }
389
390 /* 6.5.5 (4b) */
391 HCHEIGHT = HCHEIGHT + HCDH;
392 SYMWIDTH = 0;
393 TOTWIDTH = 0;
394 HCFIRSTSYM = NSYMSDECODED;
395
396 if ((int32_t) HCHEIGHT < 0) {
397 code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "invalid HCHEIGHT value");
398 goto cleanup;
399 }
400#ifdef JBIG2_DEBUG
401 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "HCHEIGHT = %d", HCHEIGHT);
402#endif
403 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "decoding height class %d with %d syms decoded", HCHEIGHT, NSYMSDECODED);
404
405 for (;;) {
406 /* 6.5.7 */
407 if (params->SDHUFF) {
408 DW = jbig2_huffman_get(hs, params->SDHUFFDW, &code);
409 } else {
410 code = jbig2_arith_int_decode(ctx, IADW, as, &DW);
411 }
412 if (code < 0)
413 {
414 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode DW");
415 goto cleanup;
416 }
417 /* 6.5.5 (4c.i) */
418 if (code > 0) {
419 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "OOB when decoding DW signals end of height class %d", HCHEIGHT);
420 break;
421 }
422
423 /* check for broken symbol table */
424 if (NSYMSDECODED >= params->SDNUMNEWSYMS) {
425 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "no OOB signaling end of height class %d, continuing", HCHEIGHT);
426 break;
427 }
428
429 SYMWIDTH = SYMWIDTH + DW;
430 TOTWIDTH = TOTWIDTH + SYMWIDTH;
431 if ((int32_t) SYMWIDTH < 0) {
432 code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "invalid SYMWIDTH value (%d) at symbol %d", SYMWIDTH, NSYMSDECODED + 1);
433 goto cleanup;
434 }
435#ifdef JBIG2_DEBUG
436 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "SYMWIDTH = %d TOTWIDTH = %d", SYMWIDTH, TOTWIDTH);
437#endif
438 /* 6.5.5 (4c.ii) */
439 if (!params->SDHUFF || params->SDREFAGG) {
440#ifdef JBIG2_DEBUG
441 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "SDHUFF = %d; SDREFAGG = %d", params->SDHUFF, params->SDREFAGG);
442#endif
443 /* 6.5.8 */
444 if (!params->SDREFAGG) {
445 Jbig2GenericRegionParams region_params;
446 int sdat_bytes;
447
448 /* Table 16 */
449 region_params.MMR = 0;
450 region_params.GBTEMPLATE = params->SDTEMPLATE;
451 region_params.TPGDON = 0;
452 region_params.USESKIP = 0;
453 sdat_bytes = params->SDTEMPLATE == 0 ? 8 : 2;
454 memcpy(region_params.gbat, params->sdat, sdat_bytes);
455
456 image = jbig2_image_new(ctx, SYMWIDTH, HCHEIGHT);
457 if (image == NULL) {
458 code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate image");
459 goto cleanup;
460 }
461
462 code = jbig2_decode_generic_region(ctx, segment, &region_params, as, image, GB_stats);
463 if (code < 0) {
464 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode generic region");
465 goto cleanup;
466 }
467
468 SDNEWSYMS->glyphs[NSYMSDECODED] = image;
469 image = NULL;
470 } else {
471 /* 6.5.8.2 refinement/aggregate symbol */
472 uint32_t REFAGGNINST;
473
474 if (params->SDHUFF) {
475 REFAGGNINST = jbig2_huffman_get(hs, params->SDHUFFAGGINST, &code);
476 } else {
477 code = jbig2_arith_int_decode(ctx, IAAI, as, (int32_t *) &REFAGGNINST);
478 }
479 if (code < 0) {
480 code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode number of symbols in aggregate glyph");
481 goto cleanup;
482 }
483 if (code > 0) {
484 code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB in number of symbols in aggregate glyph");
485 goto cleanup;
486 }
487 if ((int32_t) REFAGGNINST <= 0) {
488 code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "invalid number of symbols in aggregate glyph");
489 goto cleanup;
490 }
491
492 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "aggregate symbol coding (%d instances)", REFAGGNINST);
493
494 if (REFAGGNINST > 1) {
495 tparams.SBNUMINSTANCES = REFAGGNINST;
496
497 image = jbig2_image_new(ctx, SYMWIDTH, HCHEIGHT);
498 if (image == NULL) {
499 code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate symbol image");
500 goto cleanup;
501 }
502
503 /* multiple symbols are handled as a text region */
504 code = jbig2_decode_text_region(ctx, segment, &tparams, (const Jbig2SymbolDict * const *)refagg_dicts,
505 2, image, data, size, GR_stats, as, ws);
506 if (code < 0) {
507 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode text region");
508 goto cleanup;
509 }
510
511 SDNEWSYMS->glyphs[NSYMSDECODED] = image;
512 image = NULL;
513 } else {
514 /* 6.5.8.2.2 */
515 /* bool SBHUFF = params->SDHUFF; */
516 Jbig2RefinementRegionParams rparams;
517 uint32_t ID;
518 int32_t RDX, RDY;
519 int BMSIZE = 0;
520 uint32_t ninsyms = params->SDNUMINSYMS;
521 int code1 = 0;
522 int code2 = 0;
523 int code3 = 0;
524 int code4 = 0;
525 int code5 = 0;
526
527 /* 6.5.8.2.2 (2, 3, 4, 5) */
528 if (params->SDHUFF) {
529 ID = jbig2_huffman_get_bits(hs, SBSYMCODELEN, &code1);
530 RDX = jbig2_huffman_get(hs, tparams.SBHUFFRDX, &code2);
531 RDY = jbig2_huffman_get(hs, tparams.SBHUFFRDY, &code3);
532 BMSIZE = jbig2_huffman_get(hs, tparams.SBHUFFRSIZE, &code4);
533 code5 = jbig2_huffman_skip(hs);
534 } else {
535 code1 = jbig2_arith_iaid_decode(ctx, tparams.IAID, as, (int32_t *) &ID);
536 code2 = jbig2_arith_int_decode(ctx, tparams.IARDX, as, &RDX);
537 code3 = jbig2_arith_int_decode(ctx, tparams.IARDY, as, &RDY);
538 }
539
540 if (code1 < 0 || code2 < 0 || code3 < 0 || code4 < 0 || code5 < 0) {
541 code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode data");
542 goto cleanup;
543 }
544 if (code1 > 0 || code2 > 0 || code3 > 0 || code4 > 0 || code5 > 0) {
545 code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB in single refinement/aggregate coded symbol data");
546 goto cleanup;
547 }
548
549 if (ID >= ninsyms + NSYMSDECODED) {
550 code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "refinement references unknown symbol %d", ID);
551 goto cleanup;
552 }
553
554 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
555 "symbol is a refinement of ID %d with the refinement applied at (%d,%d)", ID, RDX, RDY);
556
557 image = jbig2_image_new(ctx, SYMWIDTH, HCHEIGHT);
558 if (image == NULL) {
559 code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate symbol image");
560 goto cleanup;
561 }
562
563 /* Table 18 */
564 rparams.GRTEMPLATE = params->SDRTEMPLATE;
565 rparams.GRREFERENCE = (ID < ninsyms) ? params->SDINSYMS->glyphs[ID] : SDNEWSYMS->glyphs[ID - ninsyms];
566 /* SumatraPDF: fail on missing glyphs */
567 if (rparams.GRREFERENCE == NULL) {
568 code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "missing glyph %d/%d", ID, ninsyms);
569 goto cleanup;
570 }
571 rparams.GRREFERENCEDX = RDX;
572 rparams.GRREFERENCEDY = RDY;
573 rparams.TPGRON = 0;
574 memcpy(rparams.grat, params->sdrat, 4);
575 code = jbig2_decode_refinement_region(ctx, segment, &rparams, as, image, GR_stats);
576 if (code < 0) {
577 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode refinement region");
578 goto cleanup;
579 }
580
581 SDNEWSYMS->glyphs[NSYMSDECODED] = image;
582 image = NULL;
583
584 /* 6.5.8.2.2 (7) */
585 if (params->SDHUFF) {
586 if (BMSIZE == 0)
587 BMSIZE = (size_t) SDNEWSYMS->glyphs[NSYMSDECODED]->height *
588 SDNEWSYMS->glyphs[NSYMSDECODED]->stride;
589 code = jbig2_huffman_advance(hs, BMSIZE);
590 if (code < 0) {
591 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to advance after huffman decoding in refinement region");
592 goto cleanup;
593 }
594 }
595 }
596 }
597
598#ifdef OUTPUT_PBM
599 {
600 char name[64];
601 FILE *out;
602 int code;
603
604 snprintf(name, 64, "sd.%04d.%04d.pbm", segment->number, NSYMSDECODED);
605 out = fopen(name, "wb");
606 code = jbig2_image_write_pbm(SDNEWSYMS->glyphs[NSYMSDECODED], out);
607 fclose(out);
608 if (code < 0) {
609 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to write glyph");
610 goto cleanup;
611 }
612 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "writing out glyph as '%s' ...", name);
613 }
614#endif
615
616 }
617
618 /* 6.5.5 (4c.iii) */
619 if (params->SDHUFF && !params->SDREFAGG) {
620 SDNEWSYMWIDTHS[NSYMSDECODED] = SYMWIDTH;
621 }
622
623 /* 6.5.5 (4c.iv) */
624 NSYMSDECODED = NSYMSDECODED + 1;
625
626 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "decoded symbol %u of %u (%ux%u)", NSYMSDECODED, params->SDNUMNEWSYMS, SYMWIDTH, HCHEIGHT);
627
628 } /* end height class decode loop */
629
630 /* 6.5.5 (4d) */
631 if (params->SDHUFF && !params->SDREFAGG) {
632 /* 6.5.9 */
633 size_t BMSIZE;
634 uint32_t j;
635 int x;
636
637 BMSIZE = jbig2_huffman_get(hs, params->SDHUFFBMSIZE, &code);
638 if (code < 0) {
639 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "error decoding size of collective bitmap");
640 goto cleanup;
641 }
642 if (code > 0) {
643 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB obtained when decoding size of collective bitmap");
644 goto cleanup;
645 }
646
647 /* skip any bits before the next byte boundary */
648 code = jbig2_huffman_skip(hs);
649 if (code < 0) {
650 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to skip to next byte when decoding collective bitmap");
651 }
652
653 image = jbig2_image_new(ctx, TOTWIDTH, HCHEIGHT);
654 if (image == NULL) {
655 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate collective bitmap image");
656 goto cleanup;
657 }
658
659 if (BMSIZE == 0) {
660 /* if BMSIZE == 0 bitmap is uncompressed */
661 const byte *src = data + jbig2_huffman_offset(hs);
662 const int stride = (image->width >> 3) + ((image->width & 7) ? 1 : 0);
663 byte *dst = image->data;
664
665 /* SumatraPDF: prevent read access violation */
666 if (size < jbig2_huffman_offset(hs) || (size - jbig2_huffman_offset(hs) < (size_t) image->height * stride) || (size < jbig2_huffman_offset(hs))) {
667 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "not enough data for decoding uncompressed (%d/%d)", image->height * stride,
668 size - jbig2_huffman_offset(hs));
669 goto cleanup;
670 }
671
672 BMSIZE = (size_t) image->height * stride;
673 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
674 "reading %dx%d uncompressed bitmap for %d symbols (%d bytes)", image->width, image->height, NSYMSDECODED - HCFIRSTSYM, BMSIZE);
675
676 for (j = 0; j < image->height; j++) {
677 memcpy(dst, src, stride);
678 dst += image->stride;
679 src += stride;
680 }
681 } else {
682 Jbig2GenericRegionParams rparams;
683
684 /* SumatraPDF: prevent read access violation */
685 if (size < jbig2_huffman_offset(hs) || size < BMSIZE || size - jbig2_huffman_offset(hs) < BMSIZE) {
686 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "not enough data for decoding (%d/%d)", BMSIZE, size - jbig2_huffman_offset(hs));
687 goto cleanup;
688 }
689
690 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
691 "reading %dx%d collective bitmap for %d symbols (%d bytes)", image->width, image->height, NSYMSDECODED - HCFIRSTSYM, BMSIZE);
692
693 rparams.MMR = 1;
694 code = jbig2_decode_generic_mmr(ctx, segment, &rparams, data + jbig2_huffman_offset(hs), BMSIZE, image);
695 if (code) {
696 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode MMR-coded generic region");
697 goto cleanup;
698 }
699 }
700
701 /* advance past the data we've just read */
702 code = jbig2_huffman_advance(hs, BMSIZE);
703 if (code < 0) {
704 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to advance after huffman decoding MMR bitmap image");
705 goto cleanup;
706 }
707
708 /* copy the collective bitmap into the symbol dictionary */
709 x = 0;
710 for (j = HCFIRSTSYM; j < NSYMSDECODED; j++) {
711 glyph = jbig2_image_new(ctx, SDNEWSYMWIDTHS[j], HCHEIGHT);
712 if (glyph == NULL) {
713 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to copy the collective bitmap into symbol dictionary");
714 goto cleanup;
715 }
716 code = jbig2_image_compose(ctx, glyph, image, -x, 0, JBIG2_COMPOSE_REPLACE);
717 if (code) {
718 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to compose image into glyph");
719 goto cleanup;
720 }
721 x += SDNEWSYMWIDTHS[j];
722 SDNEWSYMS->glyphs[j] = glyph;
723 glyph = NULL;
724 }
725 jbig2_image_release(ctx, image);
726 image = NULL;
727 }
728
729 } /* end of symbol decode loop */
730
731 /* 6.5.10 */
732 SDEXSYMS = jbig2_sd_new(ctx, params->SDNUMEXSYMS);
733 if (SDEXSYMS == NULL) {
734 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate symbols exported from symbols dictionary");
735 goto cleanup;
736 } else {
737 uint32_t i = 0;
738 uint32_t j = 0;
739 uint32_t k;
740 int exflag = 0;
741 uint32_t limit = params->SDNUMINSYMS + params->SDNUMNEWSYMS;
742 uint32_t EXRUNLENGTH;
743
744 while (i < limit) {
745 if (params->SDHUFF)
746 EXRUNLENGTH = jbig2_huffman_get(hs, tparams.SBHUFFRSIZE, &code);
747 else
748 code = jbig2_arith_int_decode(ctx, IAEX, as, (int32_t *) &EXRUNLENGTH);
749 if (code < 0) {
750 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode runlength for exported symbols");
751 /* skip to the cleanup code and return SDEXSYMS = NULL */
752 jbig2_sd_release(ctx, SDEXSYMS);
753 SDEXSYMS = NULL;
754 break;
755 }
756 if (code > 0) {
757 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB when decoding runlength for exported symbols");
758 /* skip to the cleanup code and return SDEXSYMS = NULL */
759 jbig2_sd_release(ctx, SDEXSYMS);
760 SDEXSYMS = NULL;
761 break;
762 }
763
764 /* prevent infinite list of empty runs, 1000 is just an arbitrary number */
765 if (EXRUNLENGTH <= 0 && ++emptyruns == 1000) {
766 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "runlength too small in export symbol table (%u == 0 i = %u limit = %u)", EXRUNLENGTH, i, limit);
767 /* skip to the cleanup code and return SDEXSYMS = NULL */
768 jbig2_sd_release(ctx, SDEXSYMS);
769 SDEXSYMS = NULL;
770 break;
771 } else if (EXRUNLENGTH > 0) {
772 emptyruns = 0;
773 }
774
775 if (EXRUNLENGTH > limit - i) {
776 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "exporting more symbols than available (%u > %u), capping", i + EXRUNLENGTH, limit);
777 EXRUNLENGTH = limit - i;
778 }
779 if (exflag && j + EXRUNLENGTH > params->SDNUMEXSYMS) {
780 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "exporting more symbols than may be exported (%u > %u), capping", j + EXRUNLENGTH, params->SDNUMEXSYMS);
781 EXRUNLENGTH = params->SDNUMEXSYMS - j;
782 }
783
784 for (k = 0; k < EXRUNLENGTH; k++) {
785 if (exflag) {
786 Jbig2Image *img;
787 if (i < params->SDNUMINSYMS) {
788 img = params->SDINSYMS->glyphs[i];
789 } else {
790 img = SDNEWSYMS->glyphs[i - params->SDNUMINSYMS];
791 }
792 SDEXSYMS->glyphs[j++] = jbig2_image_reference(ctx, img);
793 }
794 i++;
795 }
796 exflag = !exflag;
797 }
798 }
799
800cleanup:
801 jbig2_image_release(ctx, glyph);
802 jbig2_image_release(ctx, image);
803 if (refagg_dicts != NULL) {
804 if (refagg_dicts[0] != NULL)
805 jbig2_sd_release(ctx, refagg_dicts[0]);
806 /* skip releasing refagg_dicts[1] as that is the same as SDNEWSYMS */
807 jbig2_free(ctx->allocator, refagg_dicts);
808 }
809 jbig2_sd_release(ctx, SDNEWSYMS);
810 if (params->SDHUFF) {
811 jbig2_release_huffman_table(ctx, tparams.SBHUFFRSIZE);
812 jbig2_release_huffman_table(ctx, tparams.SBHUFFRDY);
813 jbig2_release_huffman_table(ctx, tparams.SBHUFFRDX);
814 jbig2_release_huffman_table(ctx, tparams.SBHUFFRDH);
815 jbig2_release_huffman_table(ctx, tparams.SBHUFFRDW);
816 jbig2_release_huffman_table(ctx, tparams.SBHUFFDT);
817 jbig2_release_huffman_table(ctx, tparams.SBHUFFDS);
818 jbig2_release_huffman_table(ctx, tparams.SBHUFFFS);
819 if (!params->SDREFAGG) {
820 jbig2_free(ctx->allocator, SDNEWSYMWIDTHS);
821 }
822 jbig2_huffman_free(ctx, hs);
823 } else {
824 jbig2_arith_int_ctx_free(ctx, tparams.IARDY);
825 jbig2_arith_int_ctx_free(ctx, tparams.IARDX);
826 jbig2_arith_int_ctx_free(ctx, tparams.IARDH);
827 jbig2_arith_int_ctx_free(ctx, tparams.IARDW);
828 jbig2_arith_int_ctx_free(ctx, tparams.IARI);
829 jbig2_arith_iaid_ctx_free(ctx, tparams.IAID);
830 jbig2_arith_int_ctx_free(ctx, tparams.IAIT);
831 jbig2_arith_int_ctx_free(ctx, tparams.IADS);
832 jbig2_arith_int_ctx_free(ctx, tparams.IAFS);
833 jbig2_arith_int_ctx_free(ctx, tparams.IADT);
834 jbig2_arith_int_ctx_free(ctx, IAAI);
835 jbig2_arith_int_ctx_free(ctx, IAEX);
836 jbig2_arith_int_ctx_free(ctx, IADW);
837 jbig2_arith_int_ctx_free(ctx, IADH);
838 }
839 jbig2_free(ctx->allocator, as);
840 jbig2_word_stream_buf_free(ctx, ws);
841
842 return SDEXSYMS;
843}
844
845/* 7.4.2 */
846int
847jbig2_symbol_dictionary(Jbig2Ctx *ctx, Jbig2Segment *segment, const byte *segment_data)
848{
849 Jbig2SymbolDictParams params;
850 uint16_t flags;
851 uint32_t sdat_bytes;
852 uint32_t offset;
853 Jbig2ArithCx *GB_stats = NULL;
854 Jbig2ArithCx *GR_stats = NULL;
855 int table_index = 0;
856 const Jbig2HuffmanParams *huffman_params;
857
858 params.SDHUFF = 0;
859
860 if (segment->data_length < 10)
861 goto too_short;
862
863 /* 7.4.2.1.1 */
864 flags = jbig2_get_uint16(segment_data);
865
866 /* zero params to ease cleanup later */
867 memset(&params, 0, sizeof(Jbig2SymbolDictParams));
868
869 params.SDHUFF = flags & 1;
870 params.SDREFAGG = (flags >> 1) & 1;
871 params.SDTEMPLATE = (flags >> 10) & 3;
872 params.SDRTEMPLATE = (flags >> 12) & 1;
873
874 if (params.SDHUFF) {
875 switch ((flags & 0x000c) >> 2) {
876 case 0: /* Table B.4 */
877 params.SDHUFFDH = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_D);
878 break;
879 case 1: /* Table B.5 */
880 params.SDHUFFDH = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_E);
881 break;
882 case 3: /* Custom table from referred segment */
883 huffman_params = jbig2_find_table(ctx, segment, table_index);
884 if (huffman_params == NULL) {
885 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom DH huffman table not found (%d)", table_index);
886 goto cleanup;
887 }
888 params.SDHUFFDH = jbig2_build_huffman_table(ctx, huffman_params);
889 ++table_index;
890 break;
891 case 2:
892 default:
893 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "symbol dictionary specified invalid huffman table");
894 }
895 if (params.SDHUFFDH == NULL) {
896 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate DH huffman table");
897 goto cleanup;
898 }
899
900 switch ((flags & 0x0030) >> 4) {
901 case 0: /* Table B.2 */
902 params.SDHUFFDW = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_B);
903 break;
904 case 1: /* Table B.3 */
905 params.SDHUFFDW = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_C);
906 break;
907 case 3: /* Custom table from referred segment */
908 huffman_params = jbig2_find_table(ctx, segment, table_index);
909 if (huffman_params == NULL) {
910 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom DW huffman table not found (%d)", table_index);
911 goto cleanup;
912 }
913 params.SDHUFFDW = jbig2_build_huffman_table(ctx, huffman_params);
914 ++table_index;
915 break;
916 case 2:
917 default:
918 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "symbol dictionary specified invalid huffman table");
919 goto cleanup; /* Jump direct to cleanup to avoid 2 errors being given */
920 }
921 if (params.SDHUFFDW == NULL) {
922 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate DW huffman table");
923 goto cleanup;
924 }
925
926 if (flags & 0x0040) {
927 /* Custom table from referred segment */
928 huffman_params = jbig2_find_table(ctx, segment, table_index);
929 if (huffman_params == NULL) {
930 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom BMSIZE huffman table not found (%d)", table_index);
931 goto cleanup;
932 }
933 params.SDHUFFBMSIZE = jbig2_build_huffman_table(ctx, huffman_params);
934 ++table_index;
935 } else {
936 /* Table B.1 */
937 params.SDHUFFBMSIZE = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_A);
938 }
939 if (params.SDHUFFBMSIZE == NULL) {
940 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate BMSIZE huffman table");
941 goto cleanup;
942 }
943
944 if (flags & 0x0080) {
945 /* Custom table from referred segment */
946 huffman_params = jbig2_find_table(ctx, segment, table_index);
947 if (huffman_params == NULL) {
948 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom REFAGG huffman table not found (%d)", table_index);
949 goto cleanup;
950 }
951 params.SDHUFFAGGINST = jbig2_build_huffman_table(ctx, huffman_params);
952 ++table_index;
953 } else {
954 /* Table B.1 */
955 params.SDHUFFAGGINST = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_A);
956 }
957 if (params.SDHUFFAGGINST == NULL) {
958 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate REFAGG huffman table");
959 goto cleanup;
960 }
961 }
962
963 /* FIXME: there are quite a few of these conditions to check */
964 /* maybe #ifdef CONFORMANCE and a separate routine */
965 if (!params.SDHUFF) {
966 if (flags & 0x000c) {
967 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "SDHUFF is zero, but contrary to spec SDHUFFDH is not.");
968 goto cleanup;
969 }
970 if (flags & 0x0030) {
971 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "SDHUFF is zero, but contrary to spec SDHUFFDW is not.");
972 goto cleanup;
973 }
974 }
975
976 /* 7.4.2.1.2 */
977 sdat_bytes = params.SDHUFF ? 0 : params.SDTEMPLATE == 0 ? 8 : 2;
978 memcpy(params.sdat, segment_data + 2, sdat_bytes);
979 offset = 2 + sdat_bytes;
980
981 /* 7.4.2.1.3 */
982 if (params.SDREFAGG && !params.SDRTEMPLATE) {
983 if (offset + 4 > segment->data_length)
984 goto too_short;
985 memcpy(params.sdrat, segment_data + offset, 4);
986 offset += 4;
987 }
988
989 if (offset + 8 > segment->data_length)
990 goto too_short;
991
992 /* 7.4.2.1.4 */
993 params.SDNUMEXSYMS = jbig2_get_uint32(segment_data + offset);
994 /* 7.4.2.1.5 */
995 params.SDNUMNEWSYMS = jbig2_get_uint32(segment_data + offset + 4);
996 offset += 8;
997
998 jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
999 "symbol dictionary, flags=%04x, %u exported syms, %u new syms", flags, params.SDNUMEXSYMS, params.SDNUMNEWSYMS);
1000
1001 /* 7.4.2.2 (2) */
1002 {
1003 uint32_t n_dicts = jbig2_sd_count_referred(ctx, segment);
1004 Jbig2SymbolDict **dicts = NULL;
1005
1006 if (n_dicts > 0) {
1007 dicts = jbig2_sd_list_referred(ctx, segment);
1008 if (dicts == NULL) {
1009 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate dicts in symbol dictionary");
1010 goto cleanup;
1011 }
1012 params.SDINSYMS = jbig2_sd_cat(ctx, n_dicts, dicts);
1013 if (params.SDINSYMS == NULL) {
1014 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate symbol array in symbol dictionary");
1015 jbig2_free(ctx->allocator, dicts);
1016 goto cleanup;
1017 }
1018 jbig2_free(ctx->allocator, dicts);
1019 }
1020 if (params.SDINSYMS != NULL) {
1021 params.SDNUMINSYMS = params.SDINSYMS->n_symbols;
1022 }
1023 }
1024
1025 /* 7.4.2.2 (3, 4) */
1026 if (flags & 0x0100) {
1027 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "segment marks bitmap coding context as used (NYI)");
1028 goto cleanup;
1029 } else {
1030 int stats_size = params.SDTEMPLATE == 0 ? 65536 : params.SDTEMPLATE == 1 ? 8192 : 1024;
1031
1032 GB_stats = jbig2_new(ctx, Jbig2ArithCx, stats_size);
1033 if (GB_stats == NULL) {
1034 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate arithmetic decoder states for generic regions");
1035 goto cleanup;
1036 }
1037 memset(GB_stats, 0, stats_size);
1038
1039 stats_size = params.SDRTEMPLATE ? 1 << 10 : 1 << 13;
1040 GR_stats = jbig2_new(ctx, Jbig2ArithCx, stats_size);
1041 if (GR_stats == NULL) {
1042 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate arithmetic decoder states for generic refinement regions");
1043 jbig2_free(ctx->allocator, GB_stats);
1044 goto cleanup;
1045 }
1046 memset(GR_stats, 0, sizeof (Jbig2ArithCx) * stats_size);
1047 }
1048
1049 segment->result = (void *)jbig2_decode_symbol_dict(ctx, segment, &params, segment_data + offset, segment->data_length - offset, GB_stats, GR_stats);
1050#ifdef DUMP_SYMDICT
1051 if (segment->result)
1052 jbig2_dump_symbol_dict(ctx, segment);
1053#endif
1054
1055 /* 7.4.2.2 (7) */
1056 if (flags & 0x0200) {
1057 /* todo: retain GB_stats, GR_stats */
1058 jbig2_free(ctx->allocator, GR_stats);
1059 jbig2_free(ctx->allocator, GB_stats);
1060 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "segment marks bitmap coding context as retained (NYI)");
1061 goto cleanup;
1062 } else {
1063 jbig2_free(ctx->allocator, GR_stats);
1064 jbig2_free(ctx->allocator, GB_stats);
1065 }
1066
1067cleanup:
1068 if (params.SDHUFF) {
1069 jbig2_release_huffman_table(ctx, params.SDHUFFDH);
1070 jbig2_release_huffman_table(ctx, params.SDHUFFDW);
1071 jbig2_release_huffman_table(ctx, params.SDHUFFBMSIZE);
1072 jbig2_release_huffman_table(ctx, params.SDHUFFAGGINST);
1073 }
1074 jbig2_sd_release(ctx, params.SDINSYMS);
1075
1076 return (segment->result != NULL) ? 0 : -1;
1077
1078too_short:
1079 if (params.SDHUFF) {
1080 jbig2_release_huffman_table(ctx, params.SDHUFFDH);
1081 jbig2_release_huffman_table(ctx, params.SDHUFFDW);
1082 jbig2_release_huffman_table(ctx, params.SDHUFFBMSIZE);
1083 jbig2_release_huffman_table(ctx, params.SDHUFFAGGINST);
1084 }
1085 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short");
1086}
1087