Coverage Report

Created: 2026-02-02 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/jbig2dec/jbig2_text.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
#ifdef HAVE_CONFIG_H
21
#include "config.h"
22
#endif
23
#include "os_types.h"
24
25
#include <stddef.h>
26
#include <string.h>             /* memset() */
27
28
#include "jbig2.h"
29
#include "jbig2_priv.h"
30
#include "jbig2_arith.h"
31
#include "jbig2_arith_int.h"
32
#include "jbig2_arith_iaid.h"
33
#include "jbig2_generic.h"
34
#include "jbig2_huffman.h"
35
#include "jbig2_image.h"
36
#include "jbig2_page.h"
37
#include "jbig2_refinement.h"
38
#include "jbig2_segment.h"
39
#include "jbig2_symbol_dict.h"
40
#include "jbig2_text.h"
41
42
/**
43
 * jbig2_decode_text_region: decode a text region segment
44
 *
45
 * @ctx: jbig2 decoder context
46
 * @segment: jbig2 segment (header) structure
47
 * @params: parameters from the text region header
48
 * @dicts: an array of referenced symbol dictionaries
49
 * @n_dicts: the number of referenced symbol dictionaries
50
 * @image: image structure in which to store the decoded region bitmap
51
 * @data: pointer to text region data to be decoded
52
 * @size: length of text region data
53
 *
54
 * Implements the text region decoding procedure
55
 * described in section 6.4 of the JBIG2 spec.
56
 *
57
 * returns: 0 on success
58
 **/
59
int
60
jbig2_decode_text_region(Jbig2Ctx *ctx, Jbig2Segment *segment,
61
                         const Jbig2TextRegionParams *params,
62
                         const Jbig2SymbolDict *const *dicts, const uint32_t n_dicts,
63
                         Jbig2Image *image, const byte *data, const size_t size, Jbig2ArithCx *GR_stats, Jbig2ArithState *as, Jbig2WordStream *ws)
64
4.23k
{
65
    /* relevant bits of 6.4.4 */
66
4.23k
    uint32_t NINSTANCES;
67
4.23k
    uint32_t ID;
68
4.23k
    int32_t STRIPT;
69
4.23k
    int32_t FIRSTS;
70
4.23k
    int32_t DT;
71
4.23k
    int32_t DFS;
72
4.23k
    int32_t IDS;
73
4.23k
    int32_t CURS;
74
4.23k
    int32_t CURT;
75
4.23k
    int S, T;
76
4.23k
    int x, y;
77
4.23k
    bool first_symbol;
78
4.23k
    uint32_t index, SBNUMSYMS;
79
4.23k
    Jbig2Image *IB = NULL;
80
4.23k
    Jbig2Image *IBO = NULL;
81
4.23k
    Jbig2Image *refimage = NULL;
82
4.23k
    Jbig2HuffmanState *hs = NULL;
83
4.23k
    Jbig2HuffmanTable *SBSYMCODES = NULL;
84
4.23k
    int code = 0;
85
4.23k
    int RI;
86
87
4.23k
    SBNUMSYMS = 0;
88
15.0k
    for (index = 0; index < n_dicts; index++) {
89
10.8k
        SBNUMSYMS += dicts[index]->n_symbols;
90
10.8k
    }
91
4.23k
    jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "symbol list contains %d glyphs in %d dictionaries", SBNUMSYMS, n_dicts);
92
93
4.23k
    if (params->SBHUFF) {
94
1.56k
        Jbig2HuffmanTable *runcodes = NULL;
95
1.56k
        Jbig2HuffmanParams runcodeparams;
96
1.56k
        Jbig2HuffmanLine runcodelengths[35];
97
1.56k
        Jbig2HuffmanLine *symcodelengths = NULL;
98
1.56k
        Jbig2HuffmanParams symcodeparams;
99
1.56k
        int err, len, range, r;
100
101
1.56k
        jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "huffman coded text region");
102
1.56k
        hs = jbig2_huffman_new(ctx, ws);
103
1.56k
        if (hs == NULL)
104
1
            return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region");
105
106
        /* 7.4.3.1.7 - decode symbol ID Huffman table */
107
        /* this is actually part of the segment header, but it is more
108
           convenient to handle it here */
109
110
        /* parse and build the runlength code huffman table */
111
56.1k
        for (index = 0; index < 35; index++) {
112
54.6k
            runcodelengths[index].PREFLEN = jbig2_huffman_get_bits(hs, 4, &code);
113
54.6k
            if (code < 0) {
114
0
                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to read huffman runcode lengths");
115
0
                goto cleanup1;
116
0
            }
117
54.6k
            if (code > 0) {
118
0
                jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB decoding huffman runcode lengths");
119
0
                goto cleanup1;
120
0
            }
121
54.6k
            runcodelengths[index].RANGELEN = 0;
122
54.6k
            runcodelengths[index].RANGELOW = index;
123
54.6k
            jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "  read runcode%d length %d", index, runcodelengths[index].PREFLEN);
124
54.6k
        }
125
1.56k
        runcodeparams.HTOOB = 0;
126
1.56k
        runcodeparams.lines = runcodelengths;
127
1.56k
        runcodeparams.n_lines = 35;
128
1.56k
        runcodes = jbig2_build_huffman_table(ctx, &runcodeparams);
129
1.56k
        if (runcodes == NULL) {
130
7
            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "error constructing symbol ID runcode table");
131
7
            goto cleanup1;
132
7
        }
133
134
        /* decode the symbol ID code lengths using the runlength table */
135
1.55k
        symcodelengths = jbig2_new(ctx, Jbig2HuffmanLine, SBNUMSYMS);
136
1.55k
        if (symcodelengths == NULL) {
137
1
            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate memory when reading symbol ID huffman table");
138
1
            goto cleanup1;
139
1
        }
140
1.55k
        index = 0;
141
7.68M
        while (index < SBNUMSYMS) {
142
7.68M
            code = jbig2_huffman_get(hs, runcodes, &err);
143
7.68M
            if (err < 0) {
144
1
                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "error reading symbol ID huffman table");
145
1
                goto cleanup1;
146
1
            }
147
7.68M
            if (err > 0) {
148
0
                code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB decoding symbol ID huffman table");
149
0
                goto cleanup1;
150
0
            }
151
7.68M
            if (code < 0 || code >= 35) {
152
0
                code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "symbol ID huffman table out of range");
153
0
                goto cleanup1;
154
0
            }
155
156
7.68M
            if (code < 32) {
157
7.28M
                len = code;
158
7.28M
                range = 1;
159
7.28M
            } else {
160
397k
                if (code == 32) {
161
3.01k
                    if (index < 1) {
162
1
                        code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "error decoding symbol ID table: run length with no antecedent");
163
1
                        goto cleanup1;
164
1
                    }
165
3.01k
                    len = symcodelengths[index - 1].PREFLEN;
166
394k
                } else {
167
394k
                    len = 0;    /* code == 33 or 34 */
168
394k
                }
169
397k
                err = 0;
170
397k
                if (code == 32)
171
3.01k
                    range = jbig2_huffman_get_bits(hs, 2, &err) + 3;
172
394k
                else if (code == 33)
173
390k
                    range = jbig2_huffman_get_bits(hs, 3, &err) + 3;
174
3.57k
                else if (code == 34)
175
3.57k
                    range = jbig2_huffman_get_bits(hs, 7, &err) + 11;
176
397k
                if (err < 0) {
177
0
                    code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to read huffman code");
178
0
                    goto cleanup1;
179
0
                }
180
397k
                if (err > 0) {
181
0
                    code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB decoding huffman code");
182
0
                    goto cleanup1;
183
0
                }
184
397k
            }
185
7.68M
            jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "  read runcode%d at index %d (length %d range %d)", code, index, len, range);
186
7.68M
            if (index + range > SBNUMSYMS) {
187
865
                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
188
865
                            "runlength extends %d entries beyond the end of symbol ID table", index + range - SBNUMSYMS);
189
865
                range = SBNUMSYMS - index;
190
865
            }
191
16.3M
            for (r = 0; r < range; r++) {
192
8.70M
                symcodelengths[index + r].PREFLEN = len;
193
8.70M
                symcodelengths[index + r].RANGELEN = 0;
194
8.70M
                symcodelengths[index + r].RANGELOW = index + r;
195
8.70M
            }
196
7.68M
            index += r;
197
7.68M
        }
198
199
1.55k
        if (index < SBNUMSYMS) {
200
0
            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "runlength codes do not cover the available symbol set");
201
0
            goto cleanup1;
202
0
        }
203
204
1.55k
        symcodeparams.HTOOB = 0;
205
1.55k
        symcodeparams.lines = symcodelengths;
206
1.55k
        symcodeparams.n_lines = SBNUMSYMS;
207
208
        /* skip to byte boundary */
209
1.55k
        err = jbig2_huffman_skip(hs);
210
1.55k
        if (err < 0)
211
0
        {
212
0
            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to skip to next byte when building huffman table");
213
0
            goto cleanup1;
214
0
        }
215
216
        /* finally, construct the symbol ID huffman table itself */
217
1.55k
        SBSYMCODES = jbig2_build_huffman_table(ctx, &symcodeparams);
218
219
1.56k
cleanup1:
220
1.56k
        jbig2_free(ctx->allocator, symcodelengths);
221
1.56k
        jbig2_release_huffman_table(ctx, runcodes);
222
223
1.56k
        if (SBSYMCODES == NULL) {
224
35
            jbig2_huffman_free(ctx, hs);
225
35
            return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to construct symbol ID huffman table");
226
35
        }
227
1.56k
    }
228
229
    /* 6.4.5 (1) */
230
4.19k
    jbig2_image_clear(ctx, image, params->SBDEFPIXEL);
231
232
    /* 6.4.6 */
233
4.19k
    if (params->SBHUFF) {
234
1.52k
        STRIPT = jbig2_huffman_get(hs, params->SBHUFFDT, &code);
235
2.67k
    } else {
236
2.67k
        code = jbig2_arith_int_decode(ctx, params->IADT, as, &STRIPT);
237
2.67k
    }
238
4.19k
    if (code < 0) {
239
1
        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode strip T");
240
1
        goto cleanup2;
241
1
    }
242
4.19k
    if (code > 0) {
243
2
        code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB obtained when decoding strip T");
244
2
        goto cleanup2;
245
2
    }
246
247
    /* 6.4.5 (2) */
248
4.19k
    STRIPT *= -(params->SBSTRIPS);
249
4.19k
    FIRSTS = 0;
250
4.19k
    NINSTANCES = 0;
251
252
    /* 6.4.5 (3) */
253
2.15M
    while (NINSTANCES < params->SBNUMINSTANCES) {
254
        /* (3b) */
255
2.15M
        if (params->SBHUFF) {
256
2.10M
            DT = jbig2_huffman_get(hs, params->SBHUFFDT, &code);
257
2.10M
        } else {
258
53.2k
            code = jbig2_arith_int_decode(ctx, params->IADT, as, &DT);
259
53.2k
        }
260
2.15M
        if (code < 0) {
261
1
            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode delta T");
262
1
            goto cleanup2;
263
1
        }
264
2.15M
        if (code > 0) {
265
21
            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB obtained when decoding delta T");
266
21
            goto cleanup2;
267
21
        }
268
2.15M
        DT *= params->SBSTRIPS;
269
2.15M
        STRIPT += DT;
270
271
2.15M
        first_symbol = TRUE;
272
        /* 6.4.5 (3c) - decode symbols in strip */
273
67.5M
        for (;;) {
274
            /* (3c.i) */
275
67.5M
            if (first_symbol) {
276
                /* 6.4.7 */
277
2.15M
                if (params->SBHUFF) {
278
2.10M
                    DFS = jbig2_huffman_get(hs, params->SBHUFFFS, &code);
279
2.10M
                } else {
280
53.2k
                    code = jbig2_arith_int_decode(ctx, params->IAFS, as, &DFS);
281
53.2k
                }
282
2.15M
                if (code < 0) {
283
1
                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode strip symbol S-difference");
284
1
                    goto cleanup2;
285
1
                }
286
2.15M
                if (code > 0) {
287
42
                    code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB obtained when decoding strip symbol S-difference");
288
42
                    goto cleanup2;
289
42
                }
290
2.15M
                FIRSTS += DFS;
291
2.15M
                CURS = FIRSTS;
292
2.15M
                first_symbol = FALSE;
293
65.4M
            } else {
294
65.4M
                if (NINSTANCES > params->SBNUMINSTANCES) {
295
2.43k
                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "too many NINSTANCES (%d) decoded", NINSTANCES);
296
2.43k
                    break;
297
2.43k
                }
298
                /* (3c.ii) / 6.4.8 */
299
65.4M
                if (params->SBHUFF) {
300
45.5M
                    IDS = jbig2_huffman_get(hs, params->SBHUFFDS, &code);
301
45.5M
                } else {
302
19.9M
                    code = jbig2_arith_int_decode(ctx, params->IADS, as, &IDS);
303
19.9M
                }
304
65.4M
                if (code < 0) {
305
2
                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode symbol instance S coordinate");
306
2
                    goto cleanup2;
307
2
                }
308
65.4M
                if (code > 0) {
309
2.15M
                    jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "OOB obtained when decoding symbol instance S coordinate signals end of strip with T value %d", DT);
310
2.15M
                    break;
311
2.15M
                }
312
63.2M
                CURS += IDS + params->SBDSOFFSET;
313
63.2M
            }
314
315
            /* (3c.iii) / 6.4.9 */
316
65.4M
            if (params->SBSTRIPS == 1) {
317
48.1M
                CURT = 0;
318
48.1M
            } else if (params->SBHUFF) {
319
17.1M
                CURT = jbig2_huffman_get_bits(hs, params->LOGSBSTRIPS, &code);
320
17.1M
            } else {
321
84.4k
                code = jbig2_arith_int_decode(ctx, params->IAIT, as, &CURT);
322
84.4k
            }
323
65.4M
            if (code < 0) {
324
0
                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode symbol instance T coordinate");
325
0
                goto cleanup2;
326
0
            }
327
65.4M
            if (code > 0) {
328
33
                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "OOB obtained when decoding symbol instance T coordinate");
329
33
                goto cleanup2;
330
33
            }
331
65.4M
            T = STRIPT + CURT;
332
333
            /* (3b.iv) / 6.4.10 - decode the symbol ID */
334
65.4M
            if (params->SBHUFF) {
335
45.5M
                ID = jbig2_huffman_get(hs, SBSYMCODES, &code);
336
45.5M
            } else {
337
19.9M
                code = jbig2_arith_iaid_decode(ctx, params->IAID, as, (int *)&ID);
338
19.9M
            }
339
65.4M
            if (code < 0) {
340
13
                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to obtain symbol instance symbol ID");
341
13
                goto cleanup2;
342
13
            }
343
65.4M
            if (code > 0) {
344
0
                code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB obtained when decoding symbol instance symbol ID");
345
0
                goto cleanup2;
346
0
            }
347
65.4M
            if (ID >= SBNUMSYMS) {
348
7.04M
                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "ignoring out of range symbol ID (%d/%d)", ID, SBNUMSYMS);
349
7.04M
                IB = NULL;
350
58.3M
            } else {
351
                /* (3c.v) / 6.4.11 - look up the symbol bitmap IB */
352
58.3M
                uint32_t id = ID;
353
354
58.3M
                index = 0;
355
82.7M
                while (id >= dicts[index]->n_symbols)
356
24.3M
                    id -= dicts[index++]->n_symbols;
357
58.3M
                if (dicts[index]->glyphs[id] == NULL) {
358
2.25M
                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "missing glyph (%d/%d), ignoring", index, id);
359
56.1M
                } else {
360
56.1M
                    IB = jbig2_image_reference(ctx, dicts[index]->glyphs[id]);
361
56.1M
                }
362
58.3M
            }
363
65.4M
            if (params->SBREFINE) {
364
32.4M
                if (params->SBHUFF) {
365
32.3M
                    RI = jbig2_huffman_get_bits(hs, 1, &code);
366
32.3M
                } else {
367
104k
                    code = jbig2_arith_int_decode(ctx, params->IARI, as, &RI);
368
104k
                }
369
32.4M
                if (code < 0) {
370
0
                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode symbol bitmap refinement indicator");
371
0
                    goto cleanup2;
372
0
                }
373
32.4M
                if (code > 0) {
374
13
                    code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB obtained when decoding symbol bitmap refinement indicator");
375
13
                    goto cleanup2;
376
13
                }
377
32.9M
            } else {
378
32.9M
                RI = 0;
379
32.9M
            }
380
65.4M
            if (RI) {
381
107k
                Jbig2RefinementRegionParams rparams;
382
107k
                int32_t RDW, RDH, RDX, RDY;
383
107k
                size_t BMSIZE = 0;
384
107k
                int code1 = 0;
385
107k
                int code2 = 0;
386
107k
                int code3 = 0;
387
107k
                int code4 = 0;
388
107k
                int code5 = 0;
389
107k
                int code6 = 0;
390
391
                /* 6.4.11 (1, 2, 3, 4) */
392
107k
                if (!params->SBHUFF) {
393
98.0k
                    code1 = jbig2_arith_int_decode(ctx, params->IARDW, as, &RDW);
394
98.0k
                    code2 = jbig2_arith_int_decode(ctx, params->IARDH, as, &RDH);
395
98.0k
                    code3 = jbig2_arith_int_decode(ctx, params->IARDX, as, &RDX);
396
98.0k
                    code4 = jbig2_arith_int_decode(ctx, params->IARDY, as, &RDY);
397
98.0k
                } else {
398
8.93k
                    RDW = jbig2_huffman_get(hs, params->SBHUFFRDW, &code1);
399
8.93k
                    RDH = jbig2_huffman_get(hs, params->SBHUFFRDH, &code2);
400
8.93k
                    RDX = jbig2_huffman_get(hs, params->SBHUFFRDX, &code3);
401
8.93k
                    RDY = jbig2_huffman_get(hs, params->SBHUFFRDY, &code4);
402
8.93k
                    BMSIZE = jbig2_huffman_get(hs, params->SBHUFFRSIZE, &code5);
403
8.93k
                    code6 = jbig2_huffman_skip(hs);
404
8.93k
                }
405
406
107k
                if (code1 < 0 || code2 < 0 || code3 < 0 || code4 < 0 || code5 < 0 || code6 < 0) {
407
6
                    code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode data");
408
6
                    goto cleanup2;
409
6
                }
410
107k
                if (code1 > 0 || code2 > 0 || code3 > 0 || code4 > 0 || code5 > 0 || code6 > 0) {
411
25
                    code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB obtained when decoding symbol instance refinement data");
412
25
                    goto cleanup2;
413
25
                }
414
415
                /* 6.4.11 (6) */
416
106k
                if (IB) {
417
92.6k
                    IBO = IB;
418
92.6k
                    IB = NULL;
419
92.6k
                    if (((int32_t) IBO->width) + RDW < 0 || ((int32_t) IBO->height) + RDH < 0) {
420
16
                        code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "reference image dimensions negative");
421
16
                        goto cleanup2;
422
16
                    }
423
92.5k
                    refimage = jbig2_image_new(ctx, IBO->width + RDW, IBO->height + RDH);
424
92.5k
                    if (refimage == NULL) {
425
8
                        code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate reference image");
426
8
                        goto cleanup2;
427
8
                    }
428
92.5k
                    jbig2_image_clear(ctx, refimage, 0x00);
429
430
                    /* Table 12 */
431
92.5k
                    rparams.GRTEMPLATE = params->SBRTEMPLATE;
432
92.5k
                    rparams.GRREFERENCE = IBO;
433
92.5k
                    rparams.GRREFERENCEDX = (RDW >> 1) + RDX;
434
92.5k
                    rparams.GRREFERENCEDY = (RDH >> 1) + RDY;
435
92.5k
                    rparams.TPGRON = 0;
436
92.5k
                    memcpy(rparams.grat, params->sbrat, 4);
437
92.5k
                    code = jbig2_decode_refinement_region(ctx, segment, &rparams, as, refimage, GR_stats);
438
92.5k
                    if (code < 0) {
439
8
                        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode refinement region");
440
8
                        goto cleanup2;
441
8
                    }
442
443
92.5k
                    jbig2_image_release(ctx, IBO);
444
92.5k
                    IBO = NULL;
445
92.5k
                    IB = refimage;
446
92.5k
                    refimage = NULL;
447
92.5k
                }
448
449
                /* 6.4.11 (7) */
450
106k
                if (params->SBHUFF) {
451
8.91k
                    code = jbig2_huffman_advance(hs, BMSIZE);
452
8.91k
                    if (code < 0) {
453
0
                        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to advance after huffman decoding refinement region");
454
0
                        goto cleanup2;
455
0
                    }
456
8.91k
                }
457
106k
            }
458
459
            /* (3c.vi) */
460
65.4M
            if ((!params->TRANSPOSED) && (params->REFCORNER > 1) && IB) {
461
4.80M
                CURS += IB->width - 1;
462
60.6M
            } else if ((params->TRANSPOSED) && !(params->REFCORNER & 1) && IB) {
463
5.09M
                CURS += IB->height - 1;
464
5.09M
            }
465
466
            /* (3c.vii) */
467
65.4M
            S = CURS;
468
469
            /* (3c.viii) */
470
65.4M
            if (!params->TRANSPOSED) {
471
54.0M
                switch (params->REFCORNER) {
472
20.1M
                case JBIG2_CORNER_TOPLEFT:
473
20.1M
                    x = S;
474
20.1M
                    y = T;
475
20.1M
                    break;
476
2.44M
                case JBIG2_CORNER_TOPRIGHT:
477
2.44M
                    if (IB)
478
10.8k
                        x = S - IB->width + 1;
479
2.43M
                    else
480
2.43M
                        x = S + 1;
481
2.44M
                    y = T;
482
2.44M
                    break;
483
26.6M
                case JBIG2_CORNER_BOTTOMLEFT:
484
26.6M
                    x = S;
485
26.6M
                    if (IB)
486
22.2M
                        y = T - IB->height + 1;
487
4.42M
                    else
488
4.42M
                        y = T + 1;
489
26.6M
                    break;
490
0
                default:
491
4.82M
                case JBIG2_CORNER_BOTTOMRIGHT:
492
4.82M
                    if (IB ) {
493
4.78M
                        x = S - IB->width + 1;
494
4.78M
                        y = T - IB->height + 1;
495
4.78M
                    } else {
496
39.0k
                        x = S + 1;
497
39.0k
                        y = T + 1;
498
39.0k
                    }
499
4.82M
                    break;
500
54.0M
                }
501
54.0M
            } else {            /* TRANSPOSED */
502
11.3M
                switch (params->REFCORNER) {
503
2.55k
                case JBIG2_CORNER_TOPLEFT:
504
2.55k
                    x = T;
505
2.55k
                    y = S;
506
2.55k
                    break;
507
6.26M
                case JBIG2_CORNER_TOPRIGHT:
508
6.26M
                    if (IB)
509
6.25M
                        x = T - IB->width + 1;
510
3.46k
                    else
511
3.46k
                        x = T + 1;
512
6.26M
                    y = S;
513
6.26M
                    break;
514
5.10M
                case JBIG2_CORNER_BOTTOMLEFT:
515
5.10M
                    x = T;
516
5.10M
                    if (IB)
517
5.09M
                        y = S - IB->height + 1;
518
2.61k
                    else
519
2.61k
                        y = S + 1;
520
5.10M
                    break;
521
0
                default:
522
1.30k
                case JBIG2_CORNER_BOTTOMRIGHT:
523
1.30k
                    if (IB) {
524
631
                        x = T - IB->width + 1;
525
631
                        y = S - IB->height + 1;
526
672
                    } else {
527
672
                        x = T + 1;
528
672
                        y = S + 1;
529
672
                    }
530
1.30k
                    break;
531
11.3M
                }
532
11.3M
            }
533
534
            /* (3c.ix) */
535
#ifdef JBIG2_DEBUG
536
            jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
537
                        "composing glyph ID %d: %dx%d @ (%d,%d) symbol %d/%d", ID, IB->width, IB->height, x, y, NINSTANCES + 1, params->SBNUMINSTANCES);
538
#endif
539
65.4M
            code = jbig2_image_compose(ctx, image, IB, x, y, params->SBCOMBOP);
540
65.4M
            if (code < 0) {
541
0
                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to compose symbol instance symbol bitmap into picture");
542
0
                goto cleanup2;
543
0
            }
544
545
            /* (3c.x) */
546
65.4M
            if (IB && (!params->TRANSPOSED) && (params->REFCORNER < 2)) {
547
39.9M
                CURS += IB->width - 1;
548
39.9M
            } else if (IB && (params->TRANSPOSED) && (params->REFCORNER & 1)) {
549
6.25M
                CURS += IB->height - 1;
550
6.25M
            }
551
552
            /* (3c.xi) */
553
65.4M
            NINSTANCES++;
554
555
65.4M
            jbig2_image_release(ctx, IB);
556
65.4M
            IB = NULL;
557
65.4M
        }
558
        /* end strip */
559
2.15M
    }
560
    /* 6.4.5 (4) */
561
562
4.19k
cleanup2:
563
4.19k
    jbig2_image_release(ctx, refimage);
564
4.19k
    jbig2_image_release(ctx, IBO);
565
4.19k
    jbig2_image_release(ctx, IB);
566
4.19k
    if (params->SBHUFF) {
567
1.52k
        jbig2_release_huffman_table(ctx, SBSYMCODES);
568
1.52k
    }
569
4.19k
    jbig2_huffman_free(ctx, hs);
570
571
4.19k
    return code;
572
4.19k
}
573
574
/**
575
 * jbig2_text_region: read a text region segment header
576
 **/
577
int
578
jbig2_text_region(Jbig2Ctx *ctx, Jbig2Segment *segment, const byte *segment_data)
579
2.72k
{
580
2.72k
    uint32_t offset = 0;
581
2.72k
    Jbig2RegionSegmentInfo region_info;
582
2.72k
    Jbig2TextRegionParams params;
583
2.72k
    Jbig2Image *image = NULL;
584
2.72k
    Jbig2SymbolDict **dicts = NULL;
585
2.72k
    uint32_t n_dicts = 0;
586
2.72k
    uint16_t flags = 0;
587
2.72k
    uint16_t huffman_flags = 0;
588
2.72k
    Jbig2ArithCx *GR_stats = NULL;
589
2.72k
    int code = 0;
590
2.72k
    Jbig2WordStream *ws = NULL;
591
2.72k
    Jbig2ArithState *as = NULL;
592
2.72k
    uint32_t table_index = 0;
593
2.72k
    const Jbig2HuffmanParams *huffman_params = NULL;
594
595
    /* zero params to ease cleanup later */
596
2.72k
    memset(&params, 0, sizeof(Jbig2TextRegionParams));
597
598
    /* 7.4.1 */
599
2.72k
    if (segment->data_length < 17) {
600
4
        code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short");
601
4
        goto cleanup2;
602
4
    }
603
2.72k
    jbig2_get_region_segment_info(&region_info, segment_data);
604
2.72k
    offset += 17;
605
    /* Check for T.88 amendment 3 */
606
2.72k
    if (region_info.flags & 8)
607
2
        return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "region segment flags indicate use of colored bitmap (NYI)");
608
609
    /* 7.4.3.1.1 */
610
2.72k
    if (segment->data_length - offset < 2) {
611
1
        code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short");
612
1
        goto cleanup2;
613
1
    }
614
2.72k
    flags = jbig2_get_uint16(segment_data + offset);
615
2.72k
    offset += 2;
616
617
2.72k
    jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "text region header flags 0x%04x", flags);
618
619
2.72k
    params.SBHUFF = flags & 0x0001;
620
2.72k
    params.SBREFINE = flags & 0x0002;
621
2.72k
    params.LOGSBSTRIPS = (flags & 0x000c) >> 2;
622
2.72k
    params.SBSTRIPS = 1 << params.LOGSBSTRIPS;
623
2.72k
    params.REFCORNER = (Jbig2RefCorner)((flags & 0x0030) >> 4);
624
2.72k
    params.TRANSPOSED = flags & 0x0040;
625
2.72k
    params.SBCOMBOP = (Jbig2ComposeOp)((flags & 0x0180) >> 7);
626
2.72k
    params.SBDEFPIXEL = flags & 0x0200;
627
    /* SBDSOFFSET is a signed 5 bit integer */
628
2.72k
    params.SBDSOFFSET = (flags & 0x7C00) >> 10;
629
2.72k
    if (params.SBDSOFFSET > 0x0f)
630
189
        params.SBDSOFFSET -= 0x20;
631
2.72k
    params.SBRTEMPLATE = flags & 0x8000;
632
633
2.72k
    if (params.SBDSOFFSET) {
634
1.95k
        jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "text region has SBDSOFFSET %d", params.SBDSOFFSET);
635
1.95k
    }
636
637
2.72k
    if (params.SBHUFF) {        /* Huffman coding */
638
        /* 7.4.3.1.2 */
639
519
        if (segment->data_length - offset < 2) {
640
2
            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short");
641
2
            goto cleanup2;
642
2
        }
643
517
        huffman_flags = jbig2_get_uint16(segment_data + offset);
644
517
        offset += 2;
645
646
517
        if (huffman_flags & 0x8000)
647
45
            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "reserved bit 15 of text region huffman flags is not zero");
648
2.20k
    } else {                    /* arithmetic coding */
649
650
        /* 7.4.3.1.3 */
651
2.20k
        if (segment->data_length - offset < 4) {
652
2
            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short");
653
2
            goto cleanup2;
654
2
        }
655
2.20k
        if ((params.SBREFINE) && !(params.SBRTEMPLATE)) {
656
47
            params.sbrat[0] = segment_data[offset];
657
47
            params.sbrat[1] = segment_data[offset + 1];
658
47
            params.sbrat[2] = segment_data[offset + 2];
659
47
            params.sbrat[3] = segment_data[offset + 3];
660
47
            offset += 4;
661
47
        }
662
2.20k
    }
663
664
    /* 7.4.3.1.4 */
665
2.71k
    if (segment->data_length - offset < 4) {
666
6
        code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short");
667
6
        goto cleanup2;
668
6
    }
669
2.71k
    params.SBNUMINSTANCES = jbig2_get_uint32(segment_data + offset);
670
2.71k
    offset += 4;
671
672
2.71k
    if (params.SBHUFF) {
673
        /* 7.4.3.1.5 - Symbol ID Huffman table */
674
        /* ...this is handled in the segment body decoder */
675
676
        /* 7.4.3.1.6 - Other Huffman table selection */
677
511
        switch (huffman_flags & 0x0003) {
678
417
        case 0:                /* Table B.6 */
679
417
            params.SBHUFFFS = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_F);
680
417
            break;
681
75
        case 1:                /* Table B.7 */
682
75
            params.SBHUFFFS = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_G);
683
75
            break;
684
18
        case 3:                /* Custom table from referred segment */
685
18
            huffman_params = jbig2_find_table(ctx, segment, table_index);
686
18
            if (huffman_params == NULL) {
687
5
                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom FS huffman table not found (%d)", table_index);
688
5
                goto cleanup1;
689
5
            }
690
13
            params.SBHUFFFS = jbig2_build_huffman_table(ctx, huffman_params);
691
13
            ++table_index;
692
13
            break;
693
1
        case 2:                /* invalid */
694
1
        default:
695
1
            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "text region specified invalid FS huffman table");
696
1
            goto cleanup1;
697
0
            break;
698
511
        }
699
505
        if (params.SBHUFFFS == NULL) {
700
1
            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region specified FS huffman table");
701
1
            goto cleanup1;
702
1
        }
703
704
504
        switch ((huffman_flags & 0x000c) >> 2) {
705
365
        case 0:                /* Table B.8 */
706
365
            params.SBHUFFDS = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_H);
707
365
            break;
708
63
        case 1:                /* Table B.9 */
709
63
            params.SBHUFFDS = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_I);
710
63
            break;
711
51
        case 2:                /* Table B.10 */
712
51
            params.SBHUFFDS = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_J);
713
51
            break;
714
25
        case 3:                /* Custom table from referred segment */
715
25
            huffman_params = jbig2_find_table(ctx, segment, table_index);
716
25
            if (huffman_params == NULL) {
717
4
                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom DS huffman table not found (%d)", table_index);
718
4
                goto cleanup1;
719
4
            }
720
21
            params.SBHUFFDS = jbig2_build_huffman_table(ctx, huffman_params);
721
21
            ++table_index;
722
21
            break;
723
504
        }
724
500
        if (params.SBHUFFDS == NULL) {
725
0
            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region specified DS huffman table");
726
0
            goto cleanup1;
727
0
        }
728
729
500
        switch ((huffman_flags & 0x0030) >> 4) {
730
69
        case 0:                /* Table B.11 */
731
69
            params.SBHUFFDT = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_K);
732
69
            break;
733
300
        case 1:                /* Table B.12 */
734
300
            params.SBHUFFDT = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_L);
735
300
            break;
736
118
        case 2:                /* Table B.13 */
737
118
            params.SBHUFFDT = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_M);
738
118
            break;
739
13
        case 3:                /* Custom table from referred segment */
740
13
            huffman_params = jbig2_find_table(ctx, segment, table_index);
741
13
            if (huffman_params == NULL) {
742
2
                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom DT huffman table not found (%d)", table_index);
743
2
                goto cleanup1;
744
2
            }
745
11
            params.SBHUFFDT = jbig2_build_huffman_table(ctx, huffman_params);
746
11
            ++table_index;
747
11
            break;
748
500
        }
749
498
        if (params.SBHUFFDT == NULL) {
750
1
            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region specified DT huffman table");
751
1
            goto cleanup1;
752
1
        }
753
754
497
        switch ((huffman_flags & 0x00c0) >> 6) {
755
419
        case 0:                /* Table B.14 */
756
419
            params.SBHUFFRDW = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_N);
757
419
            break;
758
55
        case 1:                /* Table B.15 */
759
55
            params.SBHUFFRDW = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O);
760
55
            break;
761
22
        case 3:                /* Custom table from referred segment */
762
22
            huffman_params = jbig2_find_table(ctx, segment, table_index);
763
22
            if (huffman_params == NULL) {
764
1
                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom RDW huffman table not found (%d)", table_index);
765
1
                goto cleanup1;
766
1
            }
767
21
            params.SBHUFFRDW = jbig2_build_huffman_table(ctx, huffman_params);
768
21
            ++table_index;
769
21
            break;
770
1
        case 2:                /* invalid */
771
1
        default:
772
1
            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "text region specified invalid RDW huffman table");
773
1
            goto cleanup1;
774
0
            break;
775
497
        }
776
495
        if (params.SBHUFFRDW == NULL) {
777
1
            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region specified RDW huffman table");
778
1
            goto cleanup1;
779
1
        }
780
781
494
        switch ((huffman_flags & 0x0300) >> 8) {
782
166
        case 0:                /* Table B.14 */
783
166
            params.SBHUFFRDH = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_N);
784
166
            break;
785
322
        case 1:                /* Table B.15 */
786
322
            params.SBHUFFRDH = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O);
787
322
            break;
788
5
        case 3:                /* Custom table from referred segment */
789
5
            huffman_params = jbig2_find_table(ctx, segment, table_index);
790
5
            if (huffman_params == NULL) {
791
2
                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom RDH huffman table not found (%d)", table_index);
792
2
                goto cleanup1;
793
2
            }
794
3
            params.SBHUFFRDH = jbig2_build_huffman_table(ctx, huffman_params);
795
3
            ++table_index;
796
3
            break;
797
1
        case 2:                /* invalid */
798
1
        default:
799
1
            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "text region specified invalid RDH huffman table");
800
1
            goto cleanup1;
801
0
            break;
802
494
        }
803
491
        if (params.SBHUFFRDH == NULL) {
804
1
            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region specified RDH huffman table");
805
1
            goto cleanup1;
806
1
        }
807
808
490
        switch ((huffman_flags & 0x0c00) >> 10) {
809
437
        case 0:                /* Table B.14 */
810
437
            params.SBHUFFRDX = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_N);
811
437
            break;
812
43
        case 1:                /* Table B.15 */
813
43
            params.SBHUFFRDX = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O);
814
43
            break;
815
8
        case 3:                /* Custom table from referred segment */
816
8
            huffman_params = jbig2_find_table(ctx, segment, table_index);
817
8
            if (huffman_params == NULL) {
818
1
                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom RDX huffman table not found (%d)", table_index);
819
1
                goto cleanup1;
820
1
            }
821
7
            params.SBHUFFRDX = jbig2_build_huffman_table(ctx, huffman_params);
822
7
            ++table_index;
823
7
            break;
824
2
        case 2:                /* invalid */
825
2
        default:
826
2
            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "text region specified invalid RDX huffman table");
827
2
            goto cleanup1;
828
0
            break;
829
490
        }
830
487
        if (params.SBHUFFRDX == NULL) {
831
1
            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region specified RDX huffman table");
832
1
            goto cleanup1;
833
1
        }
834
835
486
        switch ((huffman_flags & 0x3000) >> 12) {
836
434
        case 0:                /* Table B.14 */
837
434
            params.SBHUFFRDY = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_N);
838
434
            break;
839
42
        case 1:                /* Table B.15 */
840
42
            params.SBHUFFRDY = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O);
841
42
            break;
842
9
        case 3:                /* Custom table from referred segment */
843
9
            huffman_params = jbig2_find_table(ctx, segment, table_index);
844
9
            if (huffman_params == NULL) {
845
3
                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom RDY huffman table not found (%d)", table_index);
846
3
                goto cleanup1;
847
3
            }
848
6
            params.SBHUFFRDY = jbig2_build_huffman_table(ctx, huffman_params);
849
6
            ++table_index;
850
6
            break;
851
1
        case 2:                /* invalid */
852
1
        default:
853
1
            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "text region specified invalid RDY huffman table");
854
1
            goto cleanup1;
855
0
            break;
856
486
        }
857
482
        if (params.SBHUFFRDY == NULL) {
858
1
            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region specified RDY huffman table");
859
1
            goto cleanup1;
860
1
        }
861
862
481
        switch ((huffman_flags & 0x4000) >> 14) {
863
473
        case 0:                /* Table B.1 */
864
473
            params.SBHUFFRSIZE = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_A);
865
473
            break;
866
8
        case 1:                /* Custom table from referred segment */
867
8
            huffman_params = jbig2_find_table(ctx, segment, table_index);
868
8
            if (huffman_params == NULL) {
869
4
                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom RSIZE huffman table not found (%d)", table_index);
870
4
                goto cleanup1;
871
4
            }
872
4
            params.SBHUFFRSIZE = jbig2_build_huffman_table(ctx, huffman_params);
873
4
            ++table_index;
874
4
            break;
875
481
        }
876
477
        if (params.SBHUFFRSIZE == NULL) {
877
1
            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region specified RSIZE huffman table");
878
1
            goto cleanup1;
879
1
        }
880
881
476
        if (huffman_flags & 0x8000) {
882
20
            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "text region huffman flags bit 15 is set, contrary to spec");
883
20
        }
884
885
        /* 7.4.3.1.7 */
886
        /* For convenience this is done in the body decoder routine */
887
476
    }
888
889
2.67k
    jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
890
2.67k
                "text region: %d x %d @ (%d,%d) %d symbols", region_info.width, region_info.height, region_info.x, region_info.y, params.SBNUMINSTANCES);
891
892
    /* 7.4.3.2 (2) - compose the list of symbol dictionaries */
893
2.67k
    n_dicts = jbig2_sd_count_referred(ctx, segment);
894
2.67k
    if (n_dicts == 0) {
895
471
        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "text region refers to no symbol dictionaries");
896
2.20k
    } else {
897
2.20k
        dicts = jbig2_sd_list_referred(ctx, segment);
898
2.20k
        if (dicts == NULL) {
899
1
            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "unable to retrieve symbol dictionaries! previous parsing error?");
900
1
            goto cleanup1;
901
2.20k
        } else {
902
2.20k
            uint32_t index;
903
904
2.20k
            if (dicts[0] == NULL) {
905
0
                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unable to find first referenced symbol dictionary");
906
0
                goto cleanup1;
907
0
            }
908
8.40k
            for (index = 1; index < n_dicts; index++)
909
6.20k
                if (dicts[index] == NULL) {
910
0
                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unable to find all referenced symbol dictionaries");
911
0
                    n_dicts = index;
912
0
                }
913
2.20k
        }
914
2.20k
    }
915
916
    /* 7.4.3.2 (3) */
917
2.67k
    {
918
2.67k
        int stats_size = params.SBRTEMPLATE ? 1 << 10 : 1 << 13;
919
920
2.67k
        GR_stats = jbig2_new(ctx, Jbig2ArithCx, stats_size);
921
2.67k
        if (GR_stats == NULL) {
922
2
            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "could not allocate arithmetic decoder state");
923
2
            goto cleanup1;
924
2
        }
925
2.67k
        memset(GR_stats, 0, stats_size);
926
2.67k
    }
927
928
0
    image = jbig2_image_new(ctx, region_info.width, region_info.height);
929
2.67k
    if (image == NULL) {
930
20
        code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region image");
931
20
        goto cleanup2;
932
20
    }
933
934
2.65k
    if (offset >= segment->data_length) {
935
2
        code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short");
936
2
        goto cleanup2;
937
2
    }
938
2.65k
    ws = jbig2_word_stream_buf_new(ctx, segment_data + offset, segment->data_length - offset);
939
2.65k
    if (ws == NULL) {
940
1
        code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate word stream when handling text region image");
941
1
        goto cleanup2;
942
1
    }
943
944
2.65k
    as = jbig2_arith_new(ctx, ws);
945
2.65k
    if (as == NULL) {
946
1
        code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate arithmetic coding context when handling text region image");
947
1
        goto cleanup3;
948
1
    }
949
950
2.64k
    if (!params.SBHUFF) {
951
2.17k
        uint8_t SBSYMCODELEN;
952
2.17k
        uint32_t index;
953
2.17k
        uint32_t SBNUMSYMS = 0;
954
955
8.97k
        for (index = 0; index < n_dicts; index++) {
956
6.79k
            SBNUMSYMS += dicts[index]->n_symbols;
957
6.79k
        }
958
959
2.17k
        params.IADT = jbig2_arith_int_ctx_new(ctx);
960
2.17k
        params.IAFS = jbig2_arith_int_ctx_new(ctx);
961
2.17k
        params.IADS = jbig2_arith_int_ctx_new(ctx);
962
2.17k
        params.IAIT = jbig2_arith_int_ctx_new(ctx);
963
2.17k
        if (params.IADT == NULL || params.IAFS == NULL || params.IADS == NULL || params.IAIT == NULL) {
964
4
            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region image data");
965
4
            goto cleanup4;
966
4
        }
967
968
        /* Table 31 */
969
4.49k
        for (SBSYMCODELEN = 0; ((uint64_t) 1 << SBSYMCODELEN) < (uint64_t) SBNUMSYMS; SBSYMCODELEN++);
970
971
2.17k
        params.IAID = jbig2_arith_iaid_ctx_new(ctx, SBSYMCODELEN);
972
2.17k
        params.IARI = jbig2_arith_int_ctx_new(ctx);
973
2.17k
        params.IARDW = jbig2_arith_int_ctx_new(ctx);
974
2.17k
        params.IARDH = jbig2_arith_int_ctx_new(ctx);
975
2.17k
        params.IARDX = jbig2_arith_int_ctx_new(ctx);
976
2.17k
        params.IARDY = jbig2_arith_int_ctx_new(ctx);
977
2.17k
        if (params.IAID == NULL || params.IARI == NULL ||
978
2.16k
            params.IARDW == NULL || params.IARDH == NULL || params.IARDX == NULL || params.IARDY == NULL) {
979
11
            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region image data");
980
11
            goto cleanup5;
981
11
        }
982
2.17k
    }
983
984
2.63k
    code = jbig2_decode_text_region(ctx, segment, &params,
985
2.63k
                                    (const Jbig2SymbolDict * const *)dicts, n_dicts, image,
986
2.63k
                                    segment_data + offset, segment->data_length - offset, GR_stats, as, ws);
987
2.63k
    if (code < 0) {
988
141
        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode text region image data");
989
141
        goto cleanup5;
990
141
    }
991
992
2.49k
    if ((segment->flags & 63) == 4) {
993
        /* we have an intermediate region here. save it for later */
994
132
        segment->result = jbig2_image_reference(ctx, image);
995
2.36k
    } else {
996
        /* otherwise composite onto the page */
997
2.36k
        jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
998
2.36k
                    "composing %dx%d decoded text region onto page at (%d, %d)", region_info.width, region_info.height, region_info.x, region_info.y);
999
2.36k
        code = jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], image, region_info.x, region_info.y, region_info.op);
1000
2.36k
        if (code < 0)
1001
7
            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unable to add text region to page");
1002
2.36k
    }
1003
1004
2.64k
cleanup5:
1005
2.64k
    if (!params.SBHUFF) {
1006
2.17k
        jbig2_arith_iaid_ctx_free(ctx, params.IAID);
1007
2.17k
        jbig2_arith_int_ctx_free(ctx, params.IARI);
1008
2.17k
        jbig2_arith_int_ctx_free(ctx, params.IARDW);
1009
2.17k
        jbig2_arith_int_ctx_free(ctx, params.IARDH);
1010
2.17k
        jbig2_arith_int_ctx_free(ctx, params.IARDX);
1011
2.17k
        jbig2_arith_int_ctx_free(ctx, params.IARDY);
1012
2.17k
    }
1013
1014
2.64k
cleanup4:
1015
2.64k
    if (!params.SBHUFF) {
1016
2.17k
        jbig2_arith_int_ctx_free(ctx, params.IADT);
1017
2.17k
        jbig2_arith_int_ctx_free(ctx, params.IAFS);
1018
2.17k
        jbig2_arith_int_ctx_free(ctx, params.IADS);
1019
2.17k
        jbig2_arith_int_ctx_free(ctx, params.IAIT);
1020
2.17k
    }
1021
1022
2.65k
cleanup3:
1023
2.65k
    jbig2_free(ctx->allocator, as);
1024
2.65k
    jbig2_word_stream_buf_free(ctx, ws);
1025
1026
2.68k
cleanup2:
1027
2.68k
    jbig2_free(ctx->allocator, GR_stats);
1028
2.68k
    jbig2_image_release(ctx, image);
1029
1030
2.72k
cleanup1:
1031
2.72k
    if (params.SBHUFF) {
1032
519
        jbig2_release_huffman_table(ctx, params.SBHUFFFS);
1033
519
        jbig2_release_huffman_table(ctx, params.SBHUFFDS);
1034
519
        jbig2_release_huffman_table(ctx, params.SBHUFFDT);
1035
519
        jbig2_release_huffman_table(ctx, params.SBHUFFRDX);
1036
519
        jbig2_release_huffman_table(ctx, params.SBHUFFRDY);
1037
519
        jbig2_release_huffman_table(ctx, params.SBHUFFRDW);
1038
519
        jbig2_release_huffman_table(ctx, params.SBHUFFRDH);
1039
519
        jbig2_release_huffman_table(ctx, params.SBHUFFRSIZE);
1040
519
    }
1041
2.72k
    jbig2_free(ctx->allocator, dicts);
1042
1043
2.72k
    return code;
1044
2.68k
}