comparison mupdf-source/thirdparty/jbig2dec/jbig2_symbol_dict.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 /* Copyright (C) 2001-2023 Artifex Software, Inc.
2 All Rights Reserved.
3
4 This software is provided AS-IS with no warranty, either express or
5 implied.
6
7 This software is distributed under license and may not be copied,
8 modified or distributed except as expressly authorized under the terms
9 of the license contained in the file LICENSE in this distribution.
10
11 Refer to licensing information at http://www.artifex.com or contact
12 Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
13 CA 94129, USA, for further information.
14 */
15
16 /*
17 jbig2dec
18 */
19
20 /* 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 */
49 typedef 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
69 void
70 jbig2_dump_symbol_dict(Jbig2Ctx *ctx, Jbig2Segment *segment)
71 {
72 Jbig2SymbolDict *dict = (Jbig2SymbolDict *) segment->result;
73 uint32_t 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 */
95 Jbig2SymbolDict *
96 jbig2_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, JBIG2_UNKNOWN_SEGMENT_NUMBER, "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, JBIG2_UNKNOWN_SEGMENT_NUMBER, "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 */
121 void
122 jbig2_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 */
136 Jbig2Image *
137 jbig2_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 */
145 uint32_t
146 jbig2_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 */
163 Jbig2SymbolDict **
164 jbig2_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 */
199 Jbig2SymbolDict *
200 jbig2_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, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to allocate new symbol dictionary");
219 }
220
221 return new_dict;
222 }
223
224 /* Decoding routines */
225
226 /* 6.5 */
227 static Jbig2SymbolDict *
228 jbig2_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 uint8_t 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 for (SBSYMCODELEN = 0; ((uint64_t) 1 << SBSYMCODELEN) < ((uint64_t) params->SDNUMINSYMS + params->SDNUMNEWSYMS); SBSYMCODELEN++);
275
276 if (params->SDHUFF) {
277 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "huffman coded symbol dictionary");
278 hs = jbig2_huffman_new(ctx, ws);
279 tparams.SBHUFFRDX = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O); /* Table B.15 */
280 tparams.SBHUFFRDY = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O); /* Table B.15 */
281 tparams.SBHUFFRSIZE = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_A); /* Table B.1 */
282 if (hs == NULL || tparams.SBHUFFRDX == NULL ||
283 tparams.SBHUFFRDY == NULL || tparams.SBHUFFRSIZE == NULL) {
284 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate for symbol bitmap");
285 goto cleanup;
286 }
287 /* 6.5.5 (2) */
288 if (!params->SDREFAGG) {
289 SDNEWSYMWIDTHS = jbig2_new(ctx, uint32_t, params->SDNUMNEWSYMS);
290 if (SDNEWSYMWIDTHS == NULL) {
291 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate symbol widths (%u)", params->SDNUMNEWSYMS);
292 goto cleanup;
293 }
294 } else {
295 tparams.SBHUFFFS = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_F); /* Table B.6 */
296 tparams.SBHUFFDS = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_H); /* Table B.8 */
297 tparams.SBHUFFDT = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_K); /* Table B.11 */
298 tparams.SBHUFFRDW = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O); /* Table B.15 */
299 tparams.SBHUFFRDH = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O); /* Table B.15 */
300 if (tparams.SBHUFFFS == NULL || tparams.SBHUFFDS == NULL ||
301 tparams.SBHUFFDT == NULL || tparams.SBHUFFRDW == NULL ||
302 tparams.SBHUFFRDH == NULL) {
303 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "out of memory creating text region huffman decoder entries");
304 goto cleanup;
305 }
306 }
307 } else {
308 IADH = jbig2_arith_int_ctx_new(ctx);
309 IADW = jbig2_arith_int_ctx_new(ctx);
310 IAEX = jbig2_arith_int_ctx_new(ctx);
311 IAAI = jbig2_arith_int_ctx_new(ctx);
312 if (IADH == NULL || IADW == NULL || IAEX == NULL || IAAI == NULL) {
313 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate symbol bitmap");
314 goto cleanup;
315 }
316 tparams.IAID = jbig2_arith_iaid_ctx_new(ctx, SBSYMCODELEN);
317 tparams.IARDX = jbig2_arith_int_ctx_new(ctx);
318 tparams.IARDY = jbig2_arith_int_ctx_new(ctx);
319 if (tparams.IAID == NULL || tparams.IARDX == NULL ||
320 tparams.IARDY == NULL) {
321 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region arithmetic decoder contexts");
322 goto cleanup;
323 }
324 if (params->SDREFAGG) {
325 /* Values from Table 17, section 6.5.8.2 (2) */
326 tparams.IADT = jbig2_arith_int_ctx_new(ctx);
327 tparams.IAFS = jbig2_arith_int_ctx_new(ctx);
328 tparams.IADS = jbig2_arith_int_ctx_new(ctx);
329 tparams.IAIT = jbig2_arith_int_ctx_new(ctx);
330 /* Table 31 */
331 tparams.IARI = jbig2_arith_int_ctx_new(ctx);
332 tparams.IARDW = jbig2_arith_int_ctx_new(ctx);
333 tparams.IARDH = jbig2_arith_int_ctx_new(ctx);
334 if (tparams.IADT == NULL || tparams.IAFS == NULL ||
335 tparams.IADS == NULL || tparams.IAIT == NULL ||
336 tparams.IARI == NULL || tparams.IARDW == NULL ||
337 tparams.IARDH == NULL) {
338 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region arith decoder contexts");
339 }
340 }
341 }
342 tparams.SBHUFF = params->SDHUFF;
343 tparams.SBREFINE = 1;
344 tparams.SBSTRIPS = 1;
345 tparams.SBDEFPIXEL = 0;
346 tparams.SBCOMBOP = JBIG2_COMPOSE_OR;
347 tparams.TRANSPOSED = 0;
348 tparams.REFCORNER = JBIG2_CORNER_TOPLEFT;
349 tparams.SBDSOFFSET = 0;
350 tparams.SBRTEMPLATE = params->SDRTEMPLATE;
351
352 /* 6.5.5 (1) */
353 SDNEWSYMS = jbig2_sd_new(ctx, params->SDNUMNEWSYMS);
354 if (SDNEWSYMS == NULL) {
355 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate new symbols (%u)", params->SDNUMNEWSYMS);
356 goto cleanup;
357 }
358
359 refagg_dicts = jbig2_new(ctx, Jbig2SymbolDict *, 2);
360 if (refagg_dicts == NULL) {
361 code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "Out of memory allocating dictionary array");
362 goto cleanup;
363 }
364 refagg_dicts[0] = jbig2_sd_new(ctx, params->SDNUMINSYMS);
365 if (refagg_dicts[0] == NULL) {
366 code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "out of memory allocating symbol dictionary");
367 goto cleanup;
368 }
369 for (i = 0; i < params->SDNUMINSYMS; i++) {
370 refagg_dicts[0]->glyphs[i] = jbig2_image_reference(ctx, params->SDINSYMS->glyphs[i]);
371 }
372 refagg_dicts[1] = SDNEWSYMS;
373
374 /* 6.5.5 (4a) */
375 while (NSYMSDECODED < params->SDNUMNEWSYMS) {
376 int32_t HCDH, DW;
377
378 /* 6.5.6 */
379 if (params->SDHUFF) {
380 HCDH = jbig2_huffman_get(hs, params->SDHUFFDH, &code);
381 } else {
382 code = jbig2_arith_int_decode(ctx, IADH, as, &HCDH);
383 }
384 if (code < 0) {
385 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode height class delta");
386 goto cleanup;
387 }
388 if (code > 0) {
389 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "OOB decoding height class delta");
390 goto cleanup;
391 }
392
393 /* 6.5.5 (4b) */
394 HCHEIGHT = HCHEIGHT + HCDH;
395 SYMWIDTH = 0;
396 TOTWIDTH = 0;
397 HCFIRSTSYM = NSYMSDECODED;
398
399 if ((int32_t) HCHEIGHT < 0) {
400 code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "invalid HCHEIGHT value");
401 goto cleanup;
402 }
403 #ifdef JBIG2_DEBUG
404 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "HCHEIGHT = %d", HCHEIGHT);
405 #endif
406 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "decoding height class %d with %d syms decoded", HCHEIGHT, NSYMSDECODED);
407
408 for (;;) {
409 /* 6.5.7 */
410 if (params->SDHUFF) {
411 DW = jbig2_huffman_get(hs, params->SDHUFFDW, &code);
412 } else {
413 code = jbig2_arith_int_decode(ctx, IADW, as, &DW);
414 }
415 if (code < 0)
416 {
417 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode DW");
418 goto cleanup;
419 }
420 /* 6.5.5 (4c.i) */
421 if (code > 0) {
422 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "OOB when decoding DW signals end of height class %d", HCHEIGHT);
423 break;
424 }
425
426 /* check for broken symbol table */
427 if (NSYMSDECODED >= params->SDNUMNEWSYMS) {
428 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "no OOB signaling end of height class %d, continuing", HCHEIGHT);
429 break;
430 }
431
432 if (DW < 0 && SYMWIDTH < (uint32_t) -DW) {
433 code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "DW value (%d) would make SYMWIDTH (%u) negative at symbol %u", DW, SYMWIDTH, NSYMSDECODED + 1);
434 goto cleanup;
435 }
436 if (DW > 0 && (uint32_t) DW > UINT32_MAX - SYMWIDTH) {
437 code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "DW value (%d) would make SYMWIDTH (%u) too large at symbol %u", DW, SYMWIDTH, NSYMSDECODED + 1);
438 goto cleanup;
439 }
440
441 SYMWIDTH = SYMWIDTH + DW;
442 if (SYMWIDTH > UINT32_MAX - TOTWIDTH) {
443 code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "SYMWIDTH value (%u) would make TOTWIDTH (%u) too large at symbol %u", SYMWIDTH, TOTWIDTH, NSYMSDECODED + 1);
444 goto cleanup;
445 }
446
447 TOTWIDTH = TOTWIDTH + SYMWIDTH;
448 #ifdef JBIG2_DEBUG
449 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "SYMWIDTH = %u TOTWIDTH = %u", SYMWIDTH, TOTWIDTH);
450 #endif
451 /* 6.5.5 (4c.ii) */
452 if (!params->SDHUFF || params->SDREFAGG) {
453 #ifdef JBIG2_DEBUG
454 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "SDHUFF = %d; SDREFAGG = %d", params->SDHUFF, params->SDREFAGG);
455 #endif
456 /* 6.5.8 */
457 if (!params->SDREFAGG) {
458 Jbig2GenericRegionParams region_params;
459 int sdat_bytes;
460
461 /* Table 16 */
462 region_params.MMR = 0;
463 region_params.GBTEMPLATE = params->SDTEMPLATE;
464 region_params.TPGDON = 0;
465 region_params.USESKIP = 0;
466 sdat_bytes = params->SDTEMPLATE == 0 ? 8 : 2;
467 memcpy(region_params.gbat, params->sdat, sdat_bytes);
468
469 image = jbig2_image_new(ctx, SYMWIDTH, HCHEIGHT);
470 if (image == NULL) {
471 code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate image");
472 goto cleanup;
473 }
474
475 code = jbig2_decode_generic_region(ctx, segment, &region_params, as, image, GB_stats);
476 if (code < 0) {
477 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode generic region");
478 goto cleanup;
479 }
480
481 SDNEWSYMS->glyphs[NSYMSDECODED] = image;
482 image = NULL;
483 } else {
484 /* 6.5.8.2 refinement/aggregate symbol */
485 uint32_t REFAGGNINST;
486
487 if (params->SDHUFF) {
488 REFAGGNINST = jbig2_huffman_get(hs, params->SDHUFFAGGINST, &code);
489 } else {
490 code = jbig2_arith_int_decode(ctx, IAAI, as, (int32_t *) &REFAGGNINST);
491 }
492 if (code < 0) {
493 code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode number of symbols in aggregate glyph");
494 goto cleanup;
495 }
496 if (code > 0) {
497 code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB in number of symbols in aggregate glyph");
498 goto cleanup;
499 }
500 if ((int32_t) REFAGGNINST <= 0) {
501 code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "invalid number of symbols in aggregate glyph");
502 goto cleanup;
503 }
504
505 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "aggregate symbol coding (%d instances)", REFAGGNINST);
506
507 if (REFAGGNINST > 1) {
508 tparams.SBNUMINSTANCES = REFAGGNINST;
509
510 image = jbig2_image_new(ctx, SYMWIDTH, HCHEIGHT);
511 if (image == NULL) {
512 code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate symbol image");
513 goto cleanup;
514 }
515
516 /* multiple symbols are handled as a text region */
517 code = jbig2_decode_text_region(ctx, segment, &tparams, (const Jbig2SymbolDict * const *)refagg_dicts,
518 2, image, data, size, GR_stats, as, ws);
519 if (code < 0) {
520 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode text region");
521 goto cleanup;
522 }
523
524 SDNEWSYMS->glyphs[NSYMSDECODED] = image;
525 image = NULL;
526 } else {
527 /* 6.5.8.2.2 */
528 /* bool SBHUFF = params->SDHUFF; */
529 Jbig2RefinementRegionParams rparams;
530 uint32_t ID;
531 int32_t RDX, RDY;
532 int BMSIZE = 0;
533 uint32_t ninsyms = params->SDNUMINSYMS;
534 int code1 = 0;
535 int code2 = 0;
536 int code3 = 0;
537 int code4 = 0;
538 int code5 = 0;
539
540 /* 6.5.8.2.2 (2, 3, 4, 5) */
541 if (params->SDHUFF) {
542 ID = jbig2_huffman_get_bits(hs, SBSYMCODELEN, &code1);
543 RDX = jbig2_huffman_get(hs, tparams.SBHUFFRDX, &code2);
544 RDY = jbig2_huffman_get(hs, tparams.SBHUFFRDY, &code3);
545 BMSIZE = jbig2_huffman_get(hs, tparams.SBHUFFRSIZE, &code4);
546 code5 = jbig2_huffman_skip(hs);
547 } else {
548 code1 = jbig2_arith_iaid_decode(ctx, tparams.IAID, as, (int32_t *) &ID);
549 code2 = jbig2_arith_int_decode(ctx, tparams.IARDX, as, &RDX);
550 code3 = jbig2_arith_int_decode(ctx, tparams.IARDY, as, &RDY);
551 }
552
553 if (code1 < 0 || code2 < 0 || code3 < 0 || code4 < 0 || code5 < 0) {
554 code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode data");
555 goto cleanup;
556 }
557 if (code1 > 0 || code2 > 0 || code3 > 0 || code4 > 0 || code5 > 0) {
558 code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB in single refinement/aggregate coded symbol data");
559 goto cleanup;
560 }
561
562 if (ID >= ninsyms + NSYMSDECODED) {
563 code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "refinement references unknown symbol %d", ID);
564 goto cleanup;
565 }
566
567 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
568 "symbol is a refinement of ID %d with the refinement applied at (%d,%d)", ID, RDX, RDY);
569
570 image = jbig2_image_new(ctx, SYMWIDTH, HCHEIGHT);
571 if (image == NULL) {
572 code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate symbol image");
573 goto cleanup;
574 }
575
576 /* Table 18 */
577 rparams.GRTEMPLATE = params->SDRTEMPLATE;
578 rparams.GRREFERENCE = (ID < ninsyms) ? params->SDINSYMS->glyphs[ID] : SDNEWSYMS->glyphs[ID - ninsyms];
579 /* SumatraPDF: fail on missing glyphs */
580 if (rparams.GRREFERENCE == NULL) {
581 code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "missing glyph %d/%d", ID, ninsyms);
582 goto cleanup;
583 }
584 rparams.GRREFERENCEDX = RDX;
585 rparams.GRREFERENCEDY = RDY;
586 rparams.TPGRON = 0;
587 memcpy(rparams.grat, params->sdrat, 4);
588 code = jbig2_decode_refinement_region(ctx, segment, &rparams, as, image, GR_stats);
589 if (code < 0) {
590 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode refinement region");
591 goto cleanup;
592 }
593
594 SDNEWSYMS->glyphs[NSYMSDECODED] = image;
595 image = NULL;
596
597 /* 6.5.8.2.2 (7) */
598 if (params->SDHUFF) {
599 if (BMSIZE == 0)
600 BMSIZE = (size_t) SDNEWSYMS->glyphs[NSYMSDECODED]->height *
601 SDNEWSYMS->glyphs[NSYMSDECODED]->stride;
602 code = jbig2_huffman_advance(hs, BMSIZE);
603 if (code < 0) {
604 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to advance after huffman decoding in refinement region");
605 goto cleanup;
606 }
607 }
608 }
609 }
610
611 #ifdef OUTPUT_PBM
612 {
613 char name[64];
614 FILE *out;
615 int code;
616
617 snprintf(name, 64, "sd.%04d.%04d.pbm", segment->number, NSYMSDECODED);
618 out = fopen(name, "wb");
619 code = jbig2_image_write_pbm(SDNEWSYMS->glyphs[NSYMSDECODED], out);
620 fclose(out);
621 if (code < 0) {
622 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to write glyph");
623 goto cleanup;
624 }
625 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "writing out glyph as '%s' ...", name);
626 }
627 #endif
628
629 }
630
631 /* 6.5.5 (4c.iii) */
632 if (params->SDHUFF && !params->SDREFAGG) {
633 SDNEWSYMWIDTHS[NSYMSDECODED] = SYMWIDTH;
634 }
635
636 /* 6.5.5 (4c.iv) */
637 NSYMSDECODED = NSYMSDECODED + 1;
638
639 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "decoded symbol %u of %u (%ux%u)", NSYMSDECODED, params->SDNUMNEWSYMS, SYMWIDTH, HCHEIGHT);
640
641 } /* end height class decode loop */
642
643 /* 6.5.5 (4d) */
644 if (params->SDHUFF && !params->SDREFAGG) {
645 /* 6.5.9 */
646 size_t BMSIZE;
647 uint32_t j;
648 int x;
649
650 BMSIZE = jbig2_huffman_get(hs, params->SDHUFFBMSIZE, &code);
651 if (code < 0) {
652 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "error decoding size of collective bitmap");
653 goto cleanup;
654 }
655 if (code > 0) {
656 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB obtained when decoding size of collective bitmap");
657 goto cleanup;
658 }
659
660 /* skip any bits before the next byte boundary */
661 code = jbig2_huffman_skip(hs);
662 if (code < 0) {
663 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to skip to next byte when decoding collective bitmap");
664 }
665
666 image = jbig2_image_new(ctx, TOTWIDTH, HCHEIGHT);
667 if (image == NULL) {
668 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate collective bitmap image");
669 goto cleanup;
670 }
671
672 if (BMSIZE == 0) {
673 /* if BMSIZE == 0 bitmap is uncompressed */
674 const byte *src = data + jbig2_huffman_offset(hs);
675 const int stride = (image->width >> 3) + ((image->width & 7) ? 1 : 0);
676 byte *dst = image->data;
677
678 /* SumatraPDF: prevent read access violation */
679 if (size < jbig2_huffman_offset(hs) || (size - jbig2_huffman_offset(hs) < (size_t) image->height * stride) || (size < jbig2_huffman_offset(hs))) {
680 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "not enough data for decoding uncompressed (%d/%li)", image->height * stride,
681 (long) (size - jbig2_huffman_offset(hs)));
682 goto cleanup;
683 }
684
685 BMSIZE = (size_t) image->height * stride;
686 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
687 "reading %dx%d uncompressed bitmap for %d symbols (%li bytes)", image->width, image->height, NSYMSDECODED - HCFIRSTSYM, (long) BMSIZE);
688
689 for (j = 0; j < image->height; j++) {
690 memcpy(dst, src, stride);
691 dst += image->stride;
692 src += stride;
693 }
694 } else {
695 Jbig2GenericRegionParams rparams;
696
697 /* SumatraPDF: prevent read access violation */
698 if (size < jbig2_huffman_offset(hs) || size < BMSIZE || size - jbig2_huffman_offset(hs) < BMSIZE) {
699 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "not enough data for decoding (%li/%li)", (long) BMSIZE, (long) (size - jbig2_huffman_offset(hs)));
700 goto cleanup;
701 }
702
703 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
704 "reading %dx%d collective bitmap for %d symbols (%li bytes)", image->width, image->height, NSYMSDECODED - HCFIRSTSYM, (long) BMSIZE);
705
706 rparams.MMR = 1;
707 code = jbig2_decode_generic_mmr(ctx, segment, &rparams, data + jbig2_huffman_offset(hs), BMSIZE, image);
708 if (code) {
709 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode MMR-coded generic region");
710 goto cleanup;
711 }
712 }
713
714 /* advance past the data we've just read */
715 code = jbig2_huffman_advance(hs, BMSIZE);
716 if (code < 0) {
717 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to advance after huffman decoding MMR bitmap image");
718 goto cleanup;
719 }
720
721 /* copy the collective bitmap into the symbol dictionary */
722 x = 0;
723 for (j = HCFIRSTSYM; j < NSYMSDECODED; j++) {
724 glyph = jbig2_image_new(ctx, SDNEWSYMWIDTHS[j], HCHEIGHT);
725 if (glyph == NULL) {
726 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to copy the collective bitmap into symbol dictionary");
727 goto cleanup;
728 }
729 code = jbig2_image_compose(ctx, glyph, image, -x, 0, JBIG2_COMPOSE_REPLACE);
730 if (code) {
731 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to compose image into glyph");
732 goto cleanup;
733 }
734 x += SDNEWSYMWIDTHS[j];
735 SDNEWSYMS->glyphs[j] = glyph;
736 glyph = NULL;
737 }
738 jbig2_image_release(ctx, image);
739 image = NULL;
740 }
741
742 } /* end of symbol decode loop */
743
744 /* 6.5.10 */
745 SDEXSYMS = jbig2_sd_new(ctx, params->SDNUMEXSYMS);
746 if (SDEXSYMS == NULL) {
747 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate symbols exported from symbols dictionary");
748 goto cleanup;
749 } else {
750 uint32_t i = 0;
751 uint32_t j = 0;
752 uint32_t k;
753 int exflag = 0;
754 uint32_t limit = params->SDNUMINSYMS + params->SDNUMNEWSYMS;
755 uint32_t EXRUNLENGTH;
756
757 while (i < limit) {
758 if (params->SDHUFF)
759 EXRUNLENGTH = jbig2_huffman_get(hs, tparams.SBHUFFRSIZE, &code);
760 else
761 code = jbig2_arith_int_decode(ctx, IAEX, as, (int32_t *) &EXRUNLENGTH);
762 if (code < 0) {
763 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode runlength for exported symbols");
764 /* skip to the cleanup code and return SDEXSYMS = NULL */
765 jbig2_sd_release(ctx, SDEXSYMS);
766 SDEXSYMS = NULL;
767 break;
768 }
769 if (code > 0) {
770 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB when decoding runlength for exported symbols");
771 /* skip to the cleanup code and return SDEXSYMS = NULL */
772 jbig2_sd_release(ctx, SDEXSYMS);
773 SDEXSYMS = NULL;
774 break;
775 }
776
777 /* prevent infinite list of empty runs, 1000 is just an arbitrary number */
778 if (EXRUNLENGTH <= 0 && ++emptyruns == 1000) {
779 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "runlength too small in export symbol table (%u == 0 i = %u limit = %u)", EXRUNLENGTH, i, limit);
780 /* skip to the cleanup code and return SDEXSYMS = NULL */
781 jbig2_sd_release(ctx, SDEXSYMS);
782 SDEXSYMS = NULL;
783 break;
784 } else if (EXRUNLENGTH > 0) {
785 emptyruns = 0;
786 }
787
788 if (EXRUNLENGTH > limit - i) {
789 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "exporting more symbols than available (%u > %u), capping", i + EXRUNLENGTH, limit);
790 EXRUNLENGTH = limit - i;
791 }
792 if (exflag && j + EXRUNLENGTH > params->SDNUMEXSYMS) {
793 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "exporting more symbols than may be exported (%u > %u), capping", j + EXRUNLENGTH, params->SDNUMEXSYMS);
794 EXRUNLENGTH = params->SDNUMEXSYMS - j;
795 }
796
797 for (k = 0; k < EXRUNLENGTH; k++) {
798 if (exflag) {
799 Jbig2Image *img;
800 if (i < params->SDNUMINSYMS) {
801 img = params->SDINSYMS->glyphs[i];
802 } else {
803 img = SDNEWSYMS->glyphs[i - params->SDNUMINSYMS];
804 }
805 SDEXSYMS->glyphs[j++] = jbig2_image_reference(ctx, img);
806 }
807 i++;
808 }
809 exflag = !exflag;
810 }
811 }
812
813 cleanup:
814 jbig2_image_release(ctx, glyph);
815 jbig2_image_release(ctx, image);
816 if (refagg_dicts != NULL) {
817 if (refagg_dicts[0] != NULL)
818 jbig2_sd_release(ctx, refagg_dicts[0]);
819 /* skip releasing refagg_dicts[1] as that is the same as SDNEWSYMS */
820 jbig2_free(ctx->allocator, refagg_dicts);
821 }
822 jbig2_sd_release(ctx, SDNEWSYMS);
823 if (params->SDHUFF) {
824 jbig2_release_huffman_table(ctx, tparams.SBHUFFRSIZE);
825 jbig2_release_huffman_table(ctx, tparams.SBHUFFRDY);
826 jbig2_release_huffman_table(ctx, tparams.SBHUFFRDX);
827 jbig2_release_huffman_table(ctx, tparams.SBHUFFRDH);
828 jbig2_release_huffman_table(ctx, tparams.SBHUFFRDW);
829 jbig2_release_huffman_table(ctx, tparams.SBHUFFDT);
830 jbig2_release_huffman_table(ctx, tparams.SBHUFFDS);
831 jbig2_release_huffman_table(ctx, tparams.SBHUFFFS);
832 if (!params->SDREFAGG) {
833 jbig2_free(ctx->allocator, SDNEWSYMWIDTHS);
834 }
835 jbig2_huffman_free(ctx, hs);
836 } else {
837 jbig2_arith_int_ctx_free(ctx, tparams.IARDY);
838 jbig2_arith_int_ctx_free(ctx, tparams.IARDX);
839 jbig2_arith_int_ctx_free(ctx, tparams.IARDH);
840 jbig2_arith_int_ctx_free(ctx, tparams.IARDW);
841 jbig2_arith_int_ctx_free(ctx, tparams.IARI);
842 jbig2_arith_iaid_ctx_free(ctx, tparams.IAID);
843 jbig2_arith_int_ctx_free(ctx, tparams.IAIT);
844 jbig2_arith_int_ctx_free(ctx, tparams.IADS);
845 jbig2_arith_int_ctx_free(ctx, tparams.IAFS);
846 jbig2_arith_int_ctx_free(ctx, tparams.IADT);
847 jbig2_arith_int_ctx_free(ctx, IAAI);
848 jbig2_arith_int_ctx_free(ctx, IAEX);
849 jbig2_arith_int_ctx_free(ctx, IADW);
850 jbig2_arith_int_ctx_free(ctx, IADH);
851 }
852 jbig2_free(ctx->allocator, as);
853 jbig2_word_stream_buf_free(ctx, ws);
854
855 return SDEXSYMS;
856 }
857
858 /* 7.4.2 */
859 int
860 jbig2_symbol_dictionary(Jbig2Ctx *ctx, Jbig2Segment *segment, const byte *segment_data)
861 {
862 Jbig2SymbolDictParams params;
863 uint16_t flags;
864 uint32_t sdat_bytes;
865 uint32_t offset;
866 Jbig2ArithCx *GB_stats = NULL;
867 Jbig2ArithCx *GR_stats = NULL;
868 int table_index = 0;
869 const Jbig2HuffmanParams *huffman_params;
870
871 params.SDHUFF = 0;
872
873 if (segment->data_length < 10)
874 goto too_short;
875
876 /* 7.4.2.1.1 */
877 flags = jbig2_get_uint16(segment_data);
878
879 /* zero params to ease cleanup later */
880 memset(&params, 0, sizeof(Jbig2SymbolDictParams));
881
882 params.SDHUFF = flags & 1;
883 params.SDREFAGG = (flags >> 1) & 1;
884 params.SDTEMPLATE = (flags >> 10) & 3;
885 params.SDRTEMPLATE = (flags >> 12) & 1;
886
887 if (params.SDHUFF) {
888 switch ((flags & 0x000c) >> 2) {
889 case 0: /* Table B.4 */
890 params.SDHUFFDH = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_D);
891 break;
892 case 1: /* Table B.5 */
893 params.SDHUFFDH = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_E);
894 break;
895 case 3: /* Custom table from referred segment */
896 huffman_params = jbig2_find_table(ctx, segment, table_index);
897 if (huffman_params == NULL) {
898 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom DH huffman table not found (%d)", table_index);
899 goto cleanup;
900 }
901 params.SDHUFFDH = jbig2_build_huffman_table(ctx, huffman_params);
902 ++table_index;
903 break;
904 case 2:
905 default:
906 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "symbol dictionary specified invalid huffman table");
907 }
908 if (params.SDHUFFDH == NULL) {
909 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate DH huffman table");
910 goto cleanup;
911 }
912
913 switch ((flags & 0x0030) >> 4) {
914 case 0: /* Table B.2 */
915 params.SDHUFFDW = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_B);
916 break;
917 case 1: /* Table B.3 */
918 params.SDHUFFDW = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_C);
919 break;
920 case 3: /* Custom table from referred segment */
921 huffman_params = jbig2_find_table(ctx, segment, table_index);
922 if (huffman_params == NULL) {
923 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom DW huffman table not found (%d)", table_index);
924 goto cleanup;
925 }
926 params.SDHUFFDW = jbig2_build_huffman_table(ctx, huffman_params);
927 ++table_index;
928 break;
929 case 2:
930 default:
931 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "symbol dictionary specified invalid huffman table");
932 goto cleanup; /* Jump direct to cleanup to avoid 2 errors being given */
933 }
934 if (params.SDHUFFDW == NULL) {
935 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate DW huffman table");
936 goto cleanup;
937 }
938
939 if (flags & 0x0040) {
940 /* Custom table from referred segment */
941 huffman_params = jbig2_find_table(ctx, segment, table_index);
942 if (huffman_params == NULL) {
943 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom BMSIZE huffman table not found (%d)", table_index);
944 goto cleanup;
945 }
946 params.SDHUFFBMSIZE = jbig2_build_huffman_table(ctx, huffman_params);
947 ++table_index;
948 } else {
949 /* Table B.1 */
950 params.SDHUFFBMSIZE = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_A);
951 }
952 if (params.SDHUFFBMSIZE == NULL) {
953 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate BMSIZE huffman table");
954 goto cleanup;
955 }
956
957 if (flags & 0x0080) {
958 /* Custom table from referred segment */
959 huffman_params = jbig2_find_table(ctx, segment, table_index);
960 if (huffman_params == NULL) {
961 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom REFAGG huffman table not found (%d)", table_index);
962 goto cleanup;
963 }
964 params.SDHUFFAGGINST = jbig2_build_huffman_table(ctx, huffman_params);
965 ++table_index;
966 } else {
967 /* Table B.1 */
968 params.SDHUFFAGGINST = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_A);
969 }
970 if (params.SDHUFFAGGINST == NULL) {
971 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate REFAGG huffman table");
972 goto cleanup;
973 }
974 }
975
976 /* FIXME: there are quite a few of these conditions to check */
977 /* maybe #ifdef CONFORMANCE and a separate routine */
978 if (!params.SDHUFF) {
979 if (flags & 0x000c) {
980 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "SDHUFF is zero, but contrary to spec SDHUFFDH is not.");
981 goto cleanup;
982 }
983 if (flags & 0x0030) {
984 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "SDHUFF is zero, but contrary to spec SDHUFFDW is not.");
985 goto cleanup;
986 }
987 }
988
989 /* 7.4.2.1.2 */
990 sdat_bytes = params.SDHUFF ? 0 : params.SDTEMPLATE == 0 ? 8 : 2;
991 memcpy(params.sdat, segment_data + 2, sdat_bytes);
992 offset = 2 + sdat_bytes;
993
994 /* 7.4.2.1.3 */
995 if (params.SDREFAGG && !params.SDRTEMPLATE) {
996 if (offset + 4 > segment->data_length)
997 goto too_short;
998 memcpy(params.sdrat, segment_data + offset, 4);
999 offset += 4;
1000 }
1001
1002 if (offset + 8 > segment->data_length)
1003 goto too_short;
1004
1005 /* 7.4.2.1.4 */
1006 params.SDNUMEXSYMS = jbig2_get_uint32(segment_data + offset);
1007 /* 7.4.2.1.5 */
1008 params.SDNUMNEWSYMS = jbig2_get_uint32(segment_data + offset + 4);
1009 offset += 8;
1010
1011 jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
1012 "symbol dictionary, flags=%04x, %u exported syms, %u new syms", flags, params.SDNUMEXSYMS, params.SDNUMNEWSYMS);
1013
1014 /* 7.4.2.2 (2) */
1015 {
1016 uint32_t n_dicts = jbig2_sd_count_referred(ctx, segment);
1017 Jbig2SymbolDict **dicts = NULL;
1018
1019 if (n_dicts > 0) {
1020 dicts = jbig2_sd_list_referred(ctx, segment);
1021 if (dicts == NULL) {
1022 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate dicts in symbol dictionary");
1023 goto cleanup;
1024 }
1025 params.SDINSYMS = jbig2_sd_cat(ctx, n_dicts, dicts);
1026 if (params.SDINSYMS == NULL) {
1027 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate symbol array in symbol dictionary");
1028 jbig2_free(ctx->allocator, dicts);
1029 goto cleanup;
1030 }
1031 jbig2_free(ctx->allocator, dicts);
1032 }
1033 if (params.SDINSYMS != NULL) {
1034 params.SDNUMINSYMS = params.SDINSYMS->n_symbols;
1035 }
1036 }
1037
1038 /* 7.4.2.2 (3, 4) */
1039 if (flags & 0x0100) {
1040 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "segment marks bitmap coding context as used (NYI)");
1041 goto cleanup;
1042 } else {
1043 int stats_size = params.SDTEMPLATE == 0 ? 65536 : params.SDTEMPLATE == 1 ? 8192 : 1024;
1044
1045 GB_stats = jbig2_new(ctx, Jbig2ArithCx, stats_size);
1046 if (GB_stats == NULL) {
1047 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate arithmetic decoder states for generic regions");
1048 goto cleanup;
1049 }
1050 memset(GB_stats, 0, sizeof (Jbig2ArithCx) * stats_size);
1051
1052 stats_size = params.SDRTEMPLATE ? 1 << 10 : 1 << 13;
1053 GR_stats = jbig2_new(ctx, Jbig2ArithCx, stats_size);
1054 if (GR_stats == NULL) {
1055 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate arithmetic decoder states for generic refinement regions");
1056 jbig2_free(ctx->allocator, GB_stats);
1057 goto cleanup;
1058 }
1059 memset(GR_stats, 0, sizeof (Jbig2ArithCx) * stats_size);
1060 }
1061
1062 segment->result = (void *)jbig2_decode_symbol_dict(ctx, segment, &params, segment_data + offset, segment->data_length - offset, GB_stats, GR_stats);
1063 #ifdef DUMP_SYMDICT
1064 if (segment->result)
1065 jbig2_dump_symbol_dict(ctx, segment);
1066 #endif
1067
1068 /* 7.4.2.2 (7) */
1069 if (flags & 0x0200) {
1070 /* todo: retain GB_stats, GR_stats */
1071 jbig2_free(ctx->allocator, GR_stats);
1072 jbig2_free(ctx->allocator, GB_stats);
1073 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "segment marks bitmap coding context as retained (NYI)");
1074 goto cleanup;
1075 } else {
1076 jbig2_free(ctx->allocator, GR_stats);
1077 jbig2_free(ctx->allocator, GB_stats);
1078 }
1079
1080 cleanup:
1081 if (params.SDHUFF) {
1082 jbig2_release_huffman_table(ctx, params.SDHUFFDH);
1083 jbig2_release_huffman_table(ctx, params.SDHUFFDW);
1084 jbig2_release_huffman_table(ctx, params.SDHUFFBMSIZE);
1085 jbig2_release_huffman_table(ctx, params.SDHUFFAGGINST);
1086 }
1087 jbig2_sd_release(ctx, params.SDINSYMS);
1088
1089 return (segment->result != NULL) ? 0 : -1;
1090
1091 too_short:
1092 if (params.SDHUFF) {
1093 jbig2_release_huffman_table(ctx, params.SDHUFFDH);
1094 jbig2_release_huffman_table(ctx, params.SDHUFFDW);
1095 jbig2_release_huffman_table(ctx, params.SDHUFFBMSIZE);
1096 jbig2_release_huffman_table(ctx, params.SDHUFFAGGINST);
1097 }
1098 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short");
1099 }