Coverage Report

Created: 2026-05-30 06:11

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.0k
{
98
18.0k
    Jbig2SymbolDict *new_dict = NULL;
99
100
18.0k
    new_dict = jbig2_new(ctx, Jbig2SymbolDict, 1);
101
18.0k
    if (new_dict != NULL) {
102
18.0k
        new_dict->glyphs = jbig2_new(ctx, Jbig2Image *, n_symbols);
103
18.0k
        new_dict->n_symbols = n_symbols;
104
18.0k
    } 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.0k
    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
116
        jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to allocate glyphs for new empty symbol dictionary");
113
116
        jbig2_free(ctx->allocator, new_dict);
114
116
        return NULL;
115
116
    }
116
117
17.9k
    return new_dict;
118
18.0k
}
119
120
/* release the memory associated with a symbol dict */
121
void
122
jbig2_sd_release(Jbig2Ctx *ctx, Jbig2SymbolDict *dict)
123
22.8k
{
124
22.8k
    uint32_t i;
125
126
22.8k
    if (dict == NULL)
127
4.94k
        return;
128
17.9k
    if (dict->glyphs != NULL)
129
337M
        for (i = 0; i < dict->n_symbols; i++)
130
337M
            jbig2_image_release(ctx, dict->glyphs[i]);
131
17.9k
    jbig2_free(ctx->allocator, dict->glyphs);
132
17.9k
    jbig2_free(ctx->allocator, dict);
133
17.9k
}
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
13.9k
{
148
13.9k
    int index;
149
13.9k
    Jbig2Segment *rsegment;
150
13.9k
    uint32_t n_dicts = 0;
151
152
267k
    for (index = 0; index < segment->referred_to_segment_count; index++) {
153
253k
        rsegment = jbig2_find_segment(ctx, segment->referred_to_segments[index]);
154
253k
        if (rsegment && ((rsegment->flags & 63) == 0) &&
155
78.9k
            rsegment->result && (((Jbig2SymbolDict *) rsegment->result)->n_symbols > 0) && ((*((Jbig2SymbolDict *) rsegment->result)->glyphs) != NULL))
156
68.1k
            n_dicts++;
157
253k
    }
158
159
13.9k
    return (n_dicts);
160
13.9k
}
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
4.20k
{
166
4.20k
    int index;
167
4.20k
    Jbig2Segment *rsegment;
168
4.20k
    Jbig2SymbolDict **dicts;
169
4.20k
    uint32_t n_dicts = jbig2_sd_count_referred(ctx, segment);
170
4.20k
    uint32_t dindex = 0;
171
172
4.20k
    dicts = jbig2_new(ctx, Jbig2SymbolDict *, n_dicts);
173
4.20k
    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
116k
    for (index = 0; index < segment->referred_to_segment_count; index++) {
179
112k
        rsegment = jbig2_find_segment(ctx, segment->referred_to_segments[index]);
180
112k
        if (rsegment && ((rsegment->flags & 63) == 0) && rsegment->result &&
181
35.2k
                (((Jbig2SymbolDict *) rsegment->result)->n_symbols > 0) && ((*((Jbig2SymbolDict *) rsegment->result)->glyphs) != NULL)) {
182
            /* add this referred to symbol dictionary */
183
30.7k
            dicts[dindex++] = (Jbig2SymbolDict *) rsegment->result;
184
30.7k
        }
185
112k
    }
186
187
4.20k
    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
4.20k
    return (dicts);
195
4.20k
}
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
1.17k
{
202
1.17k
    uint32_t i, j, k, symbols;
203
1.17k
    Jbig2SymbolDict *new_dict = NULL;
204
205
    /* count the imported symbols and allocate a new array */
206
1.17k
    symbols = 0;
207
22.4k
    for (i = 0; i < n_dicts; i++)
208
21.2k
        symbols += dicts[i]->n_symbols;
209
210
    /* fill a new array with new references to glyph pointers */
211
1.17k
    new_dict = jbig2_sd_new(ctx, symbols);
212
1.17k
    if (new_dict != NULL) {
213
1.17k
        k = 0;
214
22.4k
        for (i = 0; i < n_dicts; i++)
215
11.0M
            for (j = 0; j < dicts[i]->n_symbols; j++)
216
11.0M
                new_dict->glyphs[k++] = jbig2_image_reference(ctx, dicts[i]->glyphs[j]);
217
1.17k
    } else {
218
3
        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to allocate new symbol dictionary");
219
3
    }
220
221
1.17k
    return new_dict;
222
1.17k
}
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
5.97k
{
232
5.97k
    Jbig2SymbolDict *SDNEWSYMS = NULL;
233
5.97k
    Jbig2SymbolDict *SDEXSYMS = NULL;
234
5.97k
    uint32_t HCHEIGHT;
235
5.97k
    uint32_t NSYMSDECODED;
236
5.97k
    uint32_t SYMWIDTH, TOTWIDTH;
237
5.97k
    uint32_t HCFIRSTSYM;
238
5.97k
    uint32_t *SDNEWSYMWIDTHS = NULL;
239
5.97k
    uint8_t SBSYMCODELEN = 0;
240
5.97k
    Jbig2WordStream *ws = NULL;
241
5.97k
    Jbig2HuffmanState *hs = NULL;
242
5.97k
    Jbig2ArithState *as = NULL;
243
5.97k
    Jbig2ArithIntCtx *IADH = NULL;
244
5.97k
    Jbig2ArithIntCtx *IADW = NULL;
245
5.97k
    Jbig2ArithIntCtx *IAEX = NULL;
246
5.97k
    Jbig2ArithIntCtx *IAAI = NULL;
247
5.97k
    int code = 0;
248
5.97k
    Jbig2SymbolDict **refagg_dicts = NULL;
249
5.97k
    uint32_t i;
250
5.97k
    Jbig2TextRegionParams tparams;
251
5.97k
    Jbig2Image *image = NULL;
252
5.97k
    Jbig2Image *glyph = NULL;
253
5.97k
    uint32_t emptyruns = 0;
254
255
5.97k
    memset(&tparams, 0, sizeof(tparams));
256
257
    /* 6.5.5 (3) */
258
5.97k
    HCHEIGHT = 0;
259
5.97k
    NSYMSDECODED = 0;
260
261
5.97k
    ws = jbig2_word_stream_buf_new(ctx, data, size);
262
5.97k
    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
5.97k
    as = jbig2_arith_new(ctx, ws);
268
5.97k
    if (as == NULL) {
269
4
        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate arithmetic coding state when decoding symbol dictionary");
270
4
        jbig2_word_stream_buf_free(ctx, ws);
271
4
        return NULL;
272
4
    }
273
274
28.8k
    for (SBSYMCODELEN = 0; ((uint64_t) 1 << SBSYMCODELEN) < ((uint64_t) params->SDNUMINSYMS + params->SDNUMNEWSYMS); SBSYMCODELEN++);
275
276
5.96k
    if (params->SDHUFF) {
277
3.24k
        jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "huffman coded symbol dictionary");
278
3.24k
        hs = jbig2_huffman_new(ctx, ws);
279
3.24k
        tparams.SBHUFFRDX = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O);   /* Table B.15 */
280
3.24k
        tparams.SBHUFFRDY = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O);   /* Table B.15 */
281
3.24k
        tparams.SBHUFFRSIZE = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_A); /* Table B.1 */
282
3.24k
        if (hs == NULL || tparams.SBHUFFRDX == NULL ||
283
3.24k
                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.23k
        if (!params->SDREFAGG) {
289
2.67k
            SDNEWSYMWIDTHS = jbig2_new(ctx, uint32_t, params->SDNUMNEWSYMS);
290
2.67k
            if (SDNEWSYMWIDTHS == NULL) {
291
8
                jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate symbol widths (%u)", params->SDNUMNEWSYMS);
292
8
                goto cleanup;
293
8
            }
294
2.67k
        } else {
295
565
            tparams.SBHUFFFS = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_F);    /* Table B.6 */
296
565
            tparams.SBHUFFDS = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_H);    /* Table B.8 */
297
565
            tparams.SBHUFFDT = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_K);    /* Table B.11 */
298
565
            tparams.SBHUFFRDW = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O);   /* Table B.15 */
299
565
            tparams.SBHUFFRDH = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O);   /* Table B.15 */
300
565
            if (tparams.SBHUFFFS == NULL || tparams.SBHUFFDS == NULL ||
301
559
                    tparams.SBHUFFDT == NULL || tparams.SBHUFFRDW == NULL ||
302
557
                    tparams.SBHUFFRDH == NULL) {
303
9
                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "out of memory creating text region huffman decoder entries");
304
9
                goto cleanup;
305
9
            }
306
565
        }
307
3.23k
    } else {
308
2.72k
        IADH = jbig2_arith_int_ctx_new(ctx);
309
2.72k
        IADW = jbig2_arith_int_ctx_new(ctx);
310
2.72k
        IAEX = jbig2_arith_int_ctx_new(ctx);
311
2.72k
        IAAI = jbig2_arith_int_ctx_new(ctx);
312
2.72k
        if (IADH == NULL || IADW == NULL || IAEX == NULL || IAAI == NULL) {
313
4
            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate symbol bitmap");
314
4
            goto cleanup;
315
4
        }
316
2.72k
        tparams.IAID = jbig2_arith_iaid_ctx_new(ctx, SBSYMCODELEN);
317
2.72k
        tparams.IARDX = jbig2_arith_int_ctx_new(ctx);
318
2.72k
        tparams.IARDY = jbig2_arith_int_ctx_new(ctx);
319
2.72k
        if (tparams.IAID == NULL || tparams.IARDX == NULL ||
320
2.70k
                tparams.IARDY == NULL) {
321
16
            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region arithmetic decoder contexts");
322
16
            goto cleanup;
323
16
        }
324
2.70k
        if (params->SDREFAGG) {
325
            /* Values from Table 17, section 6.5.8.2 (2) */
326
346
            tparams.IADT = jbig2_arith_int_ctx_new(ctx);
327
346
            tparams.IAFS = jbig2_arith_int_ctx_new(ctx);
328
346
            tparams.IADS = jbig2_arith_int_ctx_new(ctx);
329
346
            tparams.IAIT = jbig2_arith_int_ctx_new(ctx);
330
            /* Table 31 */
331
346
            tparams.IARI = jbig2_arith_int_ctx_new(ctx);
332
346
            tparams.IARDW = jbig2_arith_int_ctx_new(ctx);
333
346
            tparams.IARDH = jbig2_arith_int_ctx_new(ctx);
334
346
            if (tparams.IADT == NULL || tparams.IAFS == NULL ||
335
344
                    tparams.IADS == NULL || tparams.IAIT == NULL ||
336
341
                    tparams.IARI == NULL || tparams.IARDW == NULL ||
337
337
                    tparams.IARDH == NULL) {
338
10
                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region arith decoder contexts");
339
10
                goto cleanup;
340
10
            }
341
346
        }
342
2.70k
    }
343
5.91k
    tparams.SBHUFF = params->SDHUFF;
344
5.91k
    tparams.SBREFINE = 1;
345
5.91k
    tparams.SBSTRIPS = 1;
346
5.91k
    tparams.SBDEFPIXEL = 0;
347
5.91k
    tparams.SBCOMBOP = JBIG2_COMPOSE_OR;
348
5.91k
    tparams.TRANSPOSED = 0;
349
5.91k
    tparams.REFCORNER = JBIG2_CORNER_TOPLEFT;
350
5.91k
    tparams.SBDSOFFSET = 0;
351
5.91k
    tparams.SBRTEMPLATE = params->SDRTEMPLATE;
352
353
    /* 6.5.5 (1) */
354
5.91k
    SDNEWSYMS = jbig2_sd_new(ctx, params->SDNUMNEWSYMS);
355
5.91k
    if (SDNEWSYMS == NULL) {
356
24
        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate new symbols (%u)", params->SDNUMNEWSYMS);
357
24
        goto cleanup;
358
24
    }
359
360
5.89k
    refagg_dicts = jbig2_new(ctx, Jbig2SymbolDict *, 2);
361
5.89k
    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
5.89k
    refagg_dicts[0] = jbig2_sd_new(ctx, params->SDNUMINSYMS);
366
5.89k
    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
9.82M
    for (i = 0; i < params->SDNUMINSYMS; i++) {
371
9.81M
        refagg_dicts[0]->glyphs[i] = jbig2_image_reference(ctx, params->SDINSYMS->glyphs[i]);
372
9.81M
    }
373
5.88k
    refagg_dicts[1] = SDNEWSYMS;
374
375
    /* 6.5.5 (4a) */
376
1.51M
    while (NSYMSDECODED < params->SDNUMNEWSYMS) {
377
1.51M
        int32_t HCDH, DW;
378
379
        /* 6.5.6 */
380
1.51M
        if (params->SDHUFF) {
381
9.81k
            HCDH = jbig2_huffman_get(hs, params->SDHUFFDH, &code);
382
1.50M
        } else {
383
1.50M
            code = jbig2_arith_int_decode(ctx, IADH, as, &HCDH);
384
1.50M
        }
385
1.51M
        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
1.51M
        if (code > 0) {
390
8
            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "OOB decoding height class delta");
391
8
            goto cleanup;
392
8
        }
393
394
        /* 6.5.5 (4b) */
395
1.51M
        HCHEIGHT = HCHEIGHT + HCDH;
396
1.51M
        SYMWIDTH = 0;
397
1.51M
        TOTWIDTH = 0;
398
1.51M
        HCFIRSTSYM = NSYMSDECODED;
399
400
1.51M
        if ((int32_t) HCHEIGHT < 0) {
401
42
            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "invalid HCHEIGHT value");
402
42
            goto cleanup;
403
42
        }
404
#ifdef JBIG2_DEBUG
405
        jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "HCHEIGHT = %d", HCHEIGHT);
406
#endif
407
1.51M
        jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "decoding height class %d with %d syms decoded", HCHEIGHT, NSYMSDECODED);
408
409
17.1M
        for (;;) {
410
            /* 6.5.7 */
411
17.1M
            if (params->SDHUFF) {
412
15.5M
                DW = jbig2_huffman_get(hs, params->SDHUFFDW, &code);
413
15.5M
            } else {
414
1.59M
                code = jbig2_arith_int_decode(ctx, IADW, as, &DW);
415
1.59M
            }
416
17.1M
            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.1M
            if (code > 0) {
423
1.51M
                jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "OOB when decoding DW signals end of height class %d", HCHEIGHT);
424
1.51M
                break;
425
1.51M
            }
426
427
            /* check for broken symbol table */
428
15.6M
            if (NSYMSDECODED >= params->SDNUMNEWSYMS) {
429
2.59k
                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "no OOB signaling end of height class %d, continuing", HCHEIGHT);
430
2.59k
                break;
431
2.59k
            }
432
433
15.6M
            if (DW < 0 && SYMWIDTH < (uint32_t) -DW) {
434
141
                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
141
                goto cleanup;
436
141
            }
437
15.6M
            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
15.6M
            SYMWIDTH = SYMWIDTH + DW;
443
15.6M
            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
15.6M
            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
15.6M
            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
99.0k
                if (!params->SDREFAGG) {
459
94.8k
                    Jbig2GenericRegionParams region_params;
460
94.8k
                    int sdat_bytes;
461
462
                    /* Table 16 */
463
94.8k
                    region_params.MMR = 0;
464
94.8k
                    region_params.GBTEMPLATE = params->SDTEMPLATE;
465
94.8k
                    region_params.TPGDON = 0;
466
94.8k
                    region_params.USESKIP = 0;
467
94.8k
                    sdat_bytes = params->SDTEMPLATE == 0 ? 8 : 2;
468
94.8k
                    memcpy(region_params.gbat, params->sdat, sdat_bytes);
469
470
94.8k
                    image = jbig2_image_new(ctx, SYMWIDTH, HCHEIGHT);
471
94.8k
                    if (image == NULL) {
472
60
                        code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate image");
473
60
                        goto cleanup;
474
60
                    }
475
476
94.8k
                    code = jbig2_decode_generic_region(ctx, segment, &region_params, as, image, GB_stats);
477
94.8k
                    if (code < 0) {
478
32
                        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode generic region");
479
32
                        goto cleanup;
480
32
                    }
481
482
94.7k
                    SDNEWSYMS->glyphs[NSYMSDECODED] = image;
483
94.7k
                    image = NULL;
484
94.7k
                } else {
485
                    /* 6.5.8.2 refinement/aggregate symbol */
486
4.13k
                    uint32_t REFAGGNINST;
487
488
4.13k
                    if (params->SDHUFF) {
489
2.97k
                        REFAGGNINST = jbig2_huffman_get(hs, params->SDHUFFAGGINST, &code);
490
2.97k
                    } else {
491
1.16k
                        code = jbig2_arith_int_decode(ctx, IAAI, as, (int32_t *) &REFAGGNINST);
492
1.16k
                    }
493
4.13k
                    if (code < 0) {
494
1
                        code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode number of symbols in aggregate glyph");
495
1
                        goto cleanup;
496
1
                    }
497
4.13k
                    if (code > 0) {
498
2
                        code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB in number of symbols in aggregate glyph");
499
2
                        goto cleanup;
500
2
                    }
501
4.13k
                    if ((int32_t) REFAGGNINST <= 0) {
502
98
                        code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "invalid number of symbols in aggregate glyph");
503
98
                        goto cleanup;
504
98
                    }
505
506
4.03k
                    jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "aggregate symbol coding (%d instances)", REFAGGNINST);
507
508
4.03k
                    if (REFAGGNINST > 1) {
509
2.82k
                        tparams.SBNUMINSTANCES = REFAGGNINST;
510
511
2.82k
                        image = jbig2_image_new(ctx, SYMWIDTH, HCHEIGHT);
512
2.82k
                        if (image == NULL) {
513
16
                            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate symbol image");
514
16
                            goto cleanup;
515
16
                        }
516
517
                        /* multiple symbols are handled as a text region */
518
2.81k
                        code = jbig2_decode_text_region(ctx, segment, &tparams, (const Jbig2SymbolDict * const *)refagg_dicts,
519
2.81k
                                                        2, image, data, size, GR_stats, as, ws);
520
2.81k
                        if (code < 0) {
521
145
                            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode text region");
522
145
                            goto cleanup;
523
145
                        }
524
525
2.66k
                        SDNEWSYMS->glyphs[NSYMSDECODED] = image;
526
2.66k
                        image = NULL;
527
2.66k
                    } else {
528
                        /* 6.5.8.2.2 */
529
                        /* bool SBHUFF = params->SDHUFF; */
530
1.20k
                        Jbig2RefinementRegionParams rparams;
531
1.20k
                        uint32_t ID;
532
1.20k
                        int32_t RDX, RDY;
533
1.20k
                        int BMSIZE = 0;
534
1.20k
                        uint32_t ninsyms = params->SDNUMINSYMS;
535
1.20k
                        int code1 = 0;
536
1.20k
                        int code2 = 0;
537
1.20k
                        int code3 = 0;
538
1.20k
                        int code4 = 0;
539
1.20k
                        int code5 = 0;
540
541
                        /* 6.5.8.2.2 (2, 3, 4, 5) */
542
1.20k
                        if (params->SDHUFF) {
543
787
                            ID = jbig2_huffman_get_bits(hs, SBSYMCODELEN, &code1);
544
787
                            RDX = jbig2_huffman_get(hs, tparams.SBHUFFRDX, &code2);
545
787
                            RDY = jbig2_huffman_get(hs, tparams.SBHUFFRDY, &code3);
546
787
                            BMSIZE = jbig2_huffman_get(hs, tparams.SBHUFFRSIZE, &code4);
547
787
                            code5 = jbig2_huffman_skip(hs);
548
787
                        } else {
549
421
                            code1 = jbig2_arith_iaid_decode(ctx, tparams.IAID, as, (int32_t *) &ID);
550
421
                            code2 = jbig2_arith_int_decode(ctx, tparams.IARDX, as, &RDX);
551
421
                            code3 = jbig2_arith_int_decode(ctx, tparams.IARDY, as, &RDY);
552
421
                        }
553
554
1.20k
                        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.20k
                        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.20k
                        if (ID >= ninsyms + NSYMSDECODED) {
564
24
                            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "refinement references unknown symbol %d", ID);
565
24
                            goto cleanup;
566
24
                        }
567
568
1.18k
                        jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
569
1.18k
                                    "symbol is a refinement of ID %d with the refinement applied at (%d,%d)", ID, RDX, RDY);
570
571
1.18k
                        image = jbig2_image_new(ctx, SYMWIDTH, HCHEIGHT);
572
1.18k
                        if (image == NULL) {
573
1
                            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate symbol image");
574
1
                            goto cleanup;
575
1
                        }
576
577
                        /* Table 18 */
578
1.18k
                        rparams.GRTEMPLATE = params->SDRTEMPLATE;
579
1.18k
                        rparams.GRREFERENCE = (ID < ninsyms) ? params->SDINSYMS->glyphs[ID] : SDNEWSYMS->glyphs[ID - ninsyms];
580
                        /* SumatraPDF: fail on missing glyphs */
581
1.18k
                        if (rparams.GRREFERENCE == NULL) {
582
2
                            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "missing glyph %d/%d", ID, ninsyms);
583
2
                            goto cleanup;
584
2
                        }
585
1.17k
                        rparams.GRREFERENCEDX = RDX;
586
1.17k
                        rparams.GRREFERENCEDY = RDY;
587
1.17k
                        rparams.TPGRON = 0;
588
1.17k
                        memcpy(rparams.grat, params->sdrat, 4);
589
1.17k
                        code = jbig2_decode_refinement_region(ctx, segment, &rparams, as, image, GR_stats);
590
1.17k
                        if (code < 0) {
591
4
                            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode refinement region");
592
4
                            goto cleanup;
593
4
                        }
594
595
1.17k
                        SDNEWSYMS->glyphs[NSYMSDECODED] = image;
596
1.17k
                        image = NULL;
597
598
                        /* 6.5.8.2.2 (7) */
599
1.17k
                        if (params->SDHUFF) {
600
765
                            if (BMSIZE == 0)
601
341
                                BMSIZE = (size_t) SDNEWSYMS->glyphs[NSYMSDECODED]->height *
602
341
                                    SDNEWSYMS->glyphs[NSYMSDECODED]->stride;
603
765
                            code = jbig2_huffman_advance(hs, BMSIZE);
604
765
                            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
765
                        }
609
1.17k
                    }
610
4.03k
                }
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
99.0k
            }
631
632
            /* 6.5.5 (4c.iii) */
633
15.6M
            if (params->SDHUFF && !params->SDREFAGG) {
634
15.5M
                SDNEWSYMWIDTHS[NSYMSDECODED] = SYMWIDTH;
635
15.5M
            }
636
637
            /* 6.5.5 (4c.iv) */
638
15.6M
            NSYMSDECODED = NSYMSDECODED + 1;
639
640
15.6M
            jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "decoded symbol %u of %u (%ux%u)", NSYMSDECODED, params->SDNUMNEWSYMS, SYMWIDTH, HCHEIGHT);
641
642
15.6M
        }                       /* end height class decode loop */
643
644
        /* 6.5.5 (4d) */
645
1.51M
        if (params->SDHUFF && !params->SDREFAGG) {
646
            /* 6.5.9 */
647
9.12k
            size_t BMSIZE;
648
9.12k
            uint32_t j;
649
9.12k
            int x;
650
651
9.12k
            BMSIZE = jbig2_huffman_get(hs, params->SDHUFFBMSIZE, &code);
652
9.12k
            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
9.12k
            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
9.12k
            code = jbig2_huffman_skip(hs);
663
9.12k
            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
9.12k
            image = jbig2_image_new(ctx, TOTWIDTH, HCHEIGHT);
668
9.12k
            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
9.08k
            if (BMSIZE == 0) {
674
                /* if BMSIZE == 0 bitmap is uncompressed */
675
1.16k
                const byte *src = data + jbig2_huffman_offset(hs);
676
1.16k
                const int stride = (image->width >> 3) + ((image->width & 7) ? 1 : 0);
677
1.16k
                byte *dst = image->data;
678
679
                /* SumatraPDF: prevent read access violation */
680
1.16k
                if (size < jbig2_huffman_offset(hs) || (size - jbig2_huffman_offset(hs) < (size_t) image->height * stride) || (size < jbig2_huffman_offset(hs))) {
681
67
                    jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "not enough data for decoding uncompressed (%d/%li)", image->height * stride,
682
67
                                (long) (size - jbig2_huffman_offset(hs)));
683
67
                    goto cleanup;
684
67
                }
685
686
1.09k
                BMSIZE = (size_t) image->height * stride;
687
1.09k
                jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
688
1.09k
                            "reading %dx%d uncompressed bitmap for %d symbols (%li bytes)", image->width, image->height, NSYMSDECODED - HCFIRSTSYM, (long) BMSIZE);
689
690
15.3k
                for (j = 0; j < image->height; j++) {
691
14.2k
                    memcpy(dst, src, stride);
692
14.2k
                    dst += image->stride;
693
14.2k
                    src += stride;
694
14.2k
                }
695
7.92k
            } else {
696
7.92k
                Jbig2GenericRegionParams rparams;
697
698
                /* SumatraPDF: prevent read access violation */
699
7.92k
                if (size < jbig2_huffman_offset(hs) || size < BMSIZE || size - jbig2_huffman_offset(hs) < BMSIZE) {
700
86
                    jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "not enough data for decoding (%li/%li)", (long) BMSIZE, (long) (size - jbig2_huffman_offset(hs)));
701
86
                    goto cleanup;
702
86
                }
703
704
7.83k
                jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
705
7.83k
                            "reading %dx%d collective bitmap for %d symbols (%li bytes)", image->width, image->height, NSYMSDECODED - HCFIRSTSYM, (long) BMSIZE);
706
707
7.83k
                rparams.MMR = 1;
708
7.83k
                code = jbig2_decode_generic_mmr(ctx, segment, &rparams, data + jbig2_huffman_offset(hs), BMSIZE, image);
709
7.83k
                if (code) {
710
10
                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode MMR-coded generic region");
711
10
                    goto cleanup;
712
10
                }
713
7.83k
            }
714
715
            /* advance past the data we've just read */
716
8.91k
            code = jbig2_huffman_advance(hs, BMSIZE);
717
8.91k
            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.91k
            x = 0;
724
283k
            for (j = HCFIRSTSYM; j < NSYMSDECODED; j++) {
725
274k
                glyph = jbig2_image_new(ctx, SDNEWSYMWIDTHS[j], HCHEIGHT);
726
274k
                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
274k
                code = jbig2_image_compose(ctx, glyph, image, -x, 0, JBIG2_COMPOSE_REPLACE);
731
274k
                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
274k
                x += SDNEWSYMWIDTHS[j];
736
274k
                SDNEWSYMS->glyphs[j] = glyph;
737
274k
                glyph = NULL;
738
274k
            }
739
8.89k
            jbig2_image_release(ctx, image);
740
8.89k
            image = NULL;
741
8.89k
        }
742
743
1.51M
    }                           /* end of symbol decode loop */
744
745
    /* 6.5.10 */
746
5.05k
    SDEXSYMS = jbig2_sd_new(ctx, params->SDNUMEXSYMS);
747
5.05k
    if (SDEXSYMS == NULL) {
748
88
        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate symbols exported from symbols dictionary");
749
88
        goto cleanup;
750
4.96k
    } else {
751
4.96k
        uint32_t i = 0;
752
4.96k
        uint32_t j = 0;
753
4.96k
        uint32_t k;
754
4.96k
        int exflag = 0;
755
4.96k
        uint32_t limit = params->SDNUMINSYMS + params->SDNUMNEWSYMS;
756
4.96k
        uint32_t EXRUNLENGTH;
757
758
37.5k
        while (i < limit) {
759
32.6k
            if (params->SDHUFF)
760
10.4k
                EXRUNLENGTH = jbig2_huffman_get(hs, tparams.SBHUFFRSIZE, &code);
761
22.2k
            else
762
22.2k
                code = jbig2_arith_int_decode(ctx, IAEX, as, (int32_t *) &EXRUNLENGTH);
763
32.6k
            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
32.6k
            if (code > 0) {
771
17
                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
17
                jbig2_sd_release(ctx, SDEXSYMS);
774
17
                SDEXSYMS = NULL;
775
17
                break;
776
17
            }
777
778
            /* prevent infinite list of empty runs, 1000 is just an arbitrary number */
779
32.6k
            if (EXRUNLENGTH <= 0 && ++emptyruns == 1000) {
780
10
                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
10
                jbig2_sd_release(ctx, SDEXSYMS);
783
10
                SDEXSYMS = NULL;
784
10
                break;
785
32.6k
            } else if (EXRUNLENGTH > 0) {
786
19.5k
                emptyruns = 0;
787
19.5k
            }
788
789
32.6k
            if (EXRUNLENGTH > limit - i) {
790
3.61k
                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "exporting more symbols than available (%u > %u), capping", i + EXRUNLENGTH, limit);
791
3.61k
                EXRUNLENGTH = limit - i;
792
3.61k
            }
793
32.6k
            if (exflag && j + EXRUNLENGTH > params->SDNUMEXSYMS) {
794
5.34k
                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "exporting more symbols than may be exported (%u > %u), capping", j + EXRUNLENGTH, params->SDNUMEXSYMS);
795
5.34k
                EXRUNLENGTH = params->SDNUMEXSYMS - j;
796
5.34k
            }
797
798
7.75M
            for (k = 0; k < EXRUNLENGTH; k++) {
799
7.72M
                if (exflag) {
800
382k
                    Jbig2Image *img;
801
382k
                    if (i < params->SDNUMINSYMS) {
802
357k
                        img = params->SDINSYMS->glyphs[i];
803
357k
                    } else {
804
25.3k
                        img = SDNEWSYMS->glyphs[i - params->SDNUMINSYMS];
805
25.3k
                    }
806
382k
                    SDEXSYMS->glyphs[j++] = jbig2_image_reference(ctx, img);
807
382k
                }
808
7.72M
                i++;
809
7.72M
            }
810
32.6k
            exflag = !exflag;
811
32.6k
        }
812
4.96k
    }
813
814
5.96k
cleanup:
815
5.96k
    jbig2_image_release(ctx, glyph);
816
5.96k
    jbig2_image_release(ctx, image);
817
5.96k
    if (refagg_dicts != NULL) {
818
5.89k
        if (refagg_dicts[0] != NULL)
819
5.88k
            jbig2_sd_release(ctx, refagg_dicts[0]);
820
        /* skip releasing refagg_dicts[1] as that is the same as SDNEWSYMS */
821
5.89k
        jbig2_free(ctx->allocator, refagg_dicts);
822
5.89k
    }
823
5.96k
    jbig2_sd_release(ctx, SDNEWSYMS);
824
5.96k
    if (params->SDHUFF) {
825
3.24k
        jbig2_release_huffman_table(ctx, tparams.SBHUFFRSIZE);
826
3.24k
        jbig2_release_huffman_table(ctx, tparams.SBHUFFRDY);
827
3.24k
        jbig2_release_huffman_table(ctx, tparams.SBHUFFRDX);
828
3.24k
        jbig2_release_huffman_table(ctx, tparams.SBHUFFRDH);
829
3.24k
        jbig2_release_huffman_table(ctx, tparams.SBHUFFRDW);
830
3.24k
        jbig2_release_huffman_table(ctx, tparams.SBHUFFDT);
831
3.24k
        jbig2_release_huffman_table(ctx, tparams.SBHUFFDS);
832
3.24k
        jbig2_release_huffman_table(ctx, tparams.SBHUFFFS);
833
3.24k
        if (!params->SDREFAGG) {
834
2.67k
            jbig2_free(ctx->allocator, SDNEWSYMWIDTHS);
835
2.67k
        }
836
3.24k
        jbig2_huffman_free(ctx, hs);
837
3.24k
    } else {
838
2.72k
        jbig2_arith_int_ctx_free(ctx, tparams.IARDY);
839
2.72k
        jbig2_arith_int_ctx_free(ctx, tparams.IARDX);
840
2.72k
        jbig2_arith_int_ctx_free(ctx, tparams.IARDH);
841
2.72k
        jbig2_arith_int_ctx_free(ctx, tparams.IARDW);
842
2.72k
        jbig2_arith_int_ctx_free(ctx, tparams.IARI);
843
2.72k
        jbig2_arith_iaid_ctx_free(ctx, tparams.IAID);
844
2.72k
        jbig2_arith_int_ctx_free(ctx, tparams.IAIT);
845
2.72k
        jbig2_arith_int_ctx_free(ctx, tparams.IADS);
846
2.72k
        jbig2_arith_int_ctx_free(ctx, tparams.IAFS);
847
2.72k
        jbig2_arith_int_ctx_free(ctx, tparams.IADT);
848
2.72k
        jbig2_arith_int_ctx_free(ctx, IAAI);
849
2.72k
        jbig2_arith_int_ctx_free(ctx, IAEX);
850
2.72k
        jbig2_arith_int_ctx_free(ctx, IADW);
851
2.72k
        jbig2_arith_int_ctx_free(ctx, IADH);
852
2.72k
    }
853
5.96k
    jbig2_free(ctx->allocator, as);
854
5.96k
    jbig2_word_stream_buf_free(ctx, ws);
855
856
5.96k
    return SDEXSYMS;
857
5.05k
}
858
859
/* 7.4.2 */
860
int
861
jbig2_symbol_dictionary(Jbig2Ctx *ctx, Jbig2Segment *segment, const byte *segment_data)
862
6.07k
{
863
6.07k
    Jbig2SymbolDictParams params;
864
6.07k
    uint16_t flags;
865
6.07k
    uint32_t sdat_bytes;
866
6.07k
    uint32_t offset;
867
6.07k
    Jbig2ArithCx *GB_stats = NULL;
868
6.07k
    Jbig2ArithCx *GR_stats = NULL;
869
6.07k
    int table_index = 0;
870
6.07k
    const Jbig2HuffmanParams *huffman_params;
871
872
6.07k
    params.SDHUFF = 0;
873
874
6.07k
    if (segment->data_length < 10)
875
23
        goto too_short;
876
877
    /* 7.4.2.1.1 */
878
6.04k
    flags = jbig2_get_uint16(segment_data);
879
880
    /* zero params to ease cleanup later */
881
6.04k
    memset(&params, 0, sizeof(Jbig2SymbolDictParams));
882
883
6.04k
    params.SDHUFF = flags & 1;
884
6.04k
    params.SDREFAGG = (flags >> 1) & 1;
885
6.04k
    params.SDTEMPLATE = (flags >> 10) & 3;
886
6.04k
    params.SDRTEMPLATE = (flags >> 12) & 1;
887
888
6.04k
    if (params.SDHUFF) {
889
3.29k
        switch ((flags & 0x000c) >> 2) {
890
2.93k
        case 0:                /* Table B.4 */
891
2.93k
            params.SDHUFFDH = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_D);
892
2.93k
            break;
893
221
        case 1:                /* Table B.5 */
894
221
            params.SDHUFFDH = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_E);
895
221
            break;
896
140
        case 3:                /* Custom table from referred segment */
897
140
            huffman_params = jbig2_find_table(ctx, segment, table_index);
898
140
            if (huffman_params == NULL) {
899
11
                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom DH huffman table not found (%d)", table_index);
900
11
                goto cleanup;
901
11
            }
902
129
            params.SDHUFFDH = jbig2_build_huffman_table(ctx, huffman_params);
903
129
            ++table_index;
904
129
            break;
905
2
        case 2:
906
2
        default:
907
2
            return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "symbol dictionary specified invalid huffman table");
908
3.29k
        }
909
3.28k
        if (params.SDHUFFDH == NULL) {
910
3
            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate DH huffman table");
911
3
            goto cleanup;
912
3
        }
913
914
3.28k
        switch ((flags & 0x0030) >> 4) {
915
2.82k
        case 0:                /* Table B.2 */
916
2.82k
            params.SDHUFFDW = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_B);
917
2.82k
            break;
918
359
        case 1:                /* Table B.3 */
919
359
            params.SDHUFFDW = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_C);
920
359
            break;
921
94
        case 3:                /* Custom table from referred segment */
922
94
            huffman_params = jbig2_find_table(ctx, segment, table_index);
923
94
            if (huffman_params == NULL) {
924
6
                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom DW huffman table not found (%d)", table_index);
925
6
                goto cleanup;
926
6
            }
927
88
            params.SDHUFFDW = jbig2_build_huffman_table(ctx, huffman_params);
928
88
            ++table_index;
929
88
            break;
930
2
        case 2:
931
2
        default:
932
2
            jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "symbol dictionary specified invalid huffman table");
933
2
            goto cleanup;       /* Jump direct to cleanup to avoid 2 errors being given */
934
3.28k
        }
935
3.27k
        if (params.SDHUFFDW == NULL) {
936
5
            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate DW huffman table");
937
5
            goto cleanup;
938
5
        }
939
940
3.26k
        if (flags & 0x0040) {
941
            /* Custom table from referred segment */
942
135
            huffman_params = jbig2_find_table(ctx, segment, table_index);
943
135
            if (huffman_params == NULL) {
944
7
                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom BMSIZE huffman table not found (%d)", table_index);
945
7
                goto cleanup;
946
7
            }
947
128
            params.SDHUFFBMSIZE = jbig2_build_huffman_table(ctx, huffman_params);
948
128
            ++table_index;
949
3.13k
        } else {
950
            /* Table B.1 */
951
3.13k
            params.SDHUFFBMSIZE = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_A);
952
3.13k
        }
953
3.26k
        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.25k
        if (flags & 0x0080) {
959
            /* Custom table from referred segment */
960
56
            huffman_params = jbig2_find_table(ctx, segment, table_index);
961
56
            if (huffman_params == NULL) {
962
7
                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom REFAGG huffman table not found (%d)", table_index);
963
7
                goto cleanup;
964
7
            }
965
49
            params.SDHUFFAGGINST = jbig2_build_huffman_table(ctx, huffman_params);
966
49
            ++table_index;
967
3.20k
        } else {
968
            /* Table B.1 */
969
3.20k
            params.SDHUFFAGGINST = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_A);
970
3.20k
        }
971
3.25k
        if (params.SDHUFFAGGINST == NULL) {
972
1
            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate REFAGG huffman table");
973
1
            goto cleanup;
974
1
        }
975
3.25k
    }
976
977
    /* FIXME: there are quite a few of these conditions to check */
978
    /* maybe #ifdef CONFORMANCE and a separate routine */
979
6.00k
    if (!params.SDHUFF) {
980
2.75k
        if (flags & 0x000c) {
981
5
            jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "SDHUFF is zero, but contrary to spec SDHUFFDH is not.");
982
5
            goto cleanup;
983
5
        }
984
2.74k
        if (flags & 0x0030) {
985
3
            jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "SDHUFF is zero, but contrary to spec SDHUFFDW is not.");
986
3
            goto cleanup;
987
3
        }
988
2.74k
    }
989
990
    /* 7.4.2.1.2 */
991
5.99k
    sdat_bytes = params.SDHUFF ? 0 : params.SDTEMPLATE == 0 ? 8 : 2;
992
5.99k
    memcpy(params.sdat, segment_data + 2, sdat_bytes);
993
5.99k
    offset = 2 + sdat_bytes;
994
995
    /* 7.4.2.1.3 */
996
5.99k
    if (params.SDREFAGG && !params.SDRTEMPLATE) {
997
670
        if (offset + 4 > segment->data_length)
998
1
            goto too_short;
999
669
        memcpy(params.sdrat, segment_data + offset, 4);
1000
669
        offset += 4;
1001
669
    }
1002
1003
5.99k
    if (offset + 8 > segment->data_length)
1004
8
        goto too_short;
1005
1006
    /* 7.4.2.1.4 */
1007
5.98k
    params.SDNUMEXSYMS = jbig2_get_uint32(segment_data + offset);
1008
    /* 7.4.2.1.5 */
1009
5.98k
    params.SDNUMNEWSYMS = jbig2_get_uint32(segment_data + offset + 4);
1010
5.98k
    offset += 8;
1011
1012
5.98k
    jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
1013
5.98k
                "symbol dictionary, flags=%04x, %u exported syms, %u new syms", flags, params.SDNUMEXSYMS, params.SDNUMNEWSYMS);
1014
1015
    /* 7.4.2.2 (2) */
1016
5.98k
    {
1017
5.98k
        uint32_t n_dicts = jbig2_sd_count_referred(ctx, segment);
1018
5.98k
        Jbig2SymbolDict **dicts = NULL;
1019
1020
5.98k
        if (n_dicts > 0) {
1021
1.17k
            dicts = jbig2_sd_list_referred(ctx, segment);
1022
1.17k
            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
1.17k
            params.SDINSYMS = jbig2_sd_cat(ctx, n_dicts, dicts);
1027
1.17k
            if (params.SDINSYMS == NULL) {
1028
3
                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate symbol array in symbol dictionary");
1029
3
                jbig2_free(ctx->allocator, dicts);
1030
3
                goto cleanup;
1031
3
            }
1032
1.17k
            jbig2_free(ctx->allocator, dicts);
1033
1.17k
        }
1034
5.98k
        if (params.SDINSYMS != NULL) {
1035
1.17k
            params.SDNUMINSYMS = params.SDINSYMS->n_symbols;
1036
1.17k
        }
1037
5.98k
    }
1038
1039
    /* 7.4.2.2 (3, 4) */
1040
5.98k
    if (flags & 0x0100) {
1041
7
        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "segment marks bitmap coding context as used (NYI)");
1042
7
        goto cleanup;
1043
5.97k
    } else {
1044
5.97k
        int stats_size = params.SDTEMPLATE == 0 ? 65536 : params.SDTEMPLATE == 1 ? 8192 : 1024;
1045
1046
5.97k
        GB_stats = jbig2_new(ctx, Jbig2ArithCx, stats_size);
1047
5.97k
        if (GB_stats == NULL) {
1048
1
            jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate arithmetic decoder states for generic regions");
1049
1
            goto cleanup;
1050
1
        }
1051
5.97k
        memset(GB_stats, 0, sizeof (Jbig2ArithCx) * stats_size);
1052
1053
5.97k
        stats_size = params.SDRTEMPLATE ? 1 << 10 : 1 << 13;
1054
5.97k
        GR_stats = jbig2_new(ctx, Jbig2ArithCx, stats_size);
1055
5.97k
        if (GR_stats == NULL) {
1056
1
            jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate arithmetic decoder states for generic refinement regions");
1057
1
            jbig2_free(ctx->allocator, GB_stats);
1058
1
            goto cleanup;
1059
1
        }
1060
5.97k
        memset(GR_stats, 0, sizeof (Jbig2ArithCx) * stats_size);
1061
5.97k
    }
1062
1063
5.97k
    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
5.97k
    if (flags & 0x0200) {
1071
        /* todo: retain GB_stats, GR_stats */
1072
211
        jbig2_free(ctx->allocator, GR_stats);
1073
211
        jbig2_free(ctx->allocator, GB_stats);
1074
211
        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "segment marks bitmap coding context as retained (NYI)");
1075
211
        goto cleanup;
1076
5.76k
    } else {
1077
5.76k
        jbig2_free(ctx->allocator, GR_stats);
1078
5.76k
        jbig2_free(ctx->allocator, GB_stats);
1079
5.76k
    }
1080
1081
6.03k
cleanup:
1082
6.03k
    if (params.SDHUFF) {
1083
3.29k
        jbig2_release_huffman_table(ctx, params.SDHUFFDH);
1084
3.29k
        jbig2_release_huffman_table(ctx, params.SDHUFFDW);
1085
3.29k
        jbig2_release_huffman_table(ctx, params.SDHUFFBMSIZE);
1086
3.29k
        jbig2_release_huffman_table(ctx, params.SDHUFFAGGINST);
1087
3.29k
    }
1088
6.03k
    jbig2_sd_release(ctx, params.SDINSYMS);
1089
1090
6.03k
    return (segment->result != NULL) ? 0 : -1;
1091
1092
32
too_short:
1093
32
    if (params.SDHUFF) {
1094
3
        jbig2_release_huffman_table(ctx, params.SDHUFFDH);
1095
3
        jbig2_release_huffman_table(ctx, params.SDHUFFDW);
1096
3
        jbig2_release_huffman_table(ctx, params.SDHUFFBMSIZE);
1097
3
        jbig2_release_huffman_table(ctx, params.SDHUFFAGGINST);
1098
3
    }
1099
32
    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short");
1100
5.97k
}