Coverage Report

Created: 2025-12-08 06:47

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