Coverage Report

Created: 2026-10-28 08:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/pcl/pxl/pxparse.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
/* pxparse.c */
18
/* PCL XL parser */
19
20
#include "memory_.h"
21
#include "gdebug.h"
22
#include "gserrors.h"
23
#include "gsio.h"
24
#include "gstypes.h"
25
#include "plparse.h"
26
#include "pxattr.h"
27
#include "pxenum.h"
28
#include "pxerrors.h"
29
#include "pxoper.h"
30
#include "pxtag.h"
31
#include "pxvalue.h"
32
#include "pxparse.h"            /* requires pxattr.h, pxvalue.h */
33
#include "pxptable.h"           /* requires pxenum.h, pxoper.h, pxvalue.h */
34
#include "pxstate.h"
35
#include "pxpthr.h"
36
#include "gsstruct.h"
37
#include "pxgstate.h"           /* Prototype for px_high_level_pattern */
38
39
/*
40
 * We define the syntax of each possible tag by 4 parameters:
41
 *  - The minimum number of input bytes required to parse it;
42
 *  - A mask and match value for the state(s) in which it is legal;
43
 *  - A transition mask to be xor'ed with the state.
44
 * See pxparse.h for the state mask values.
45
 */
46
typedef struct px_tag_syntax_s
47
{
48
    byte min_input;
49
    byte state_value;
50
    byte state_mask;
51
    byte state_transition;
52
} px_tag_syntax_t;
53
54
/* Define the common syntaxes. */
55
#define N (ptsData|ptsReading)  /* normal state */
56
#define I {1,0,0,0}             /* illegal or unusual */
57
#define P {1,ptsInPage,ptsInPage|N,0}   /* ordinary operator */
58
#define C {1,ptsInSession,ptsInSession|N,0}     /* control operator */
59
#define R(p,r,t)  /* reading operator */\
60
 {1,ptsInSession|p|r,ptsInSession|p|N,t}
61
#define D(n) {n,0,ptsData,ptsData}      /* data type */
62
#define DI D(1)                 /* invalid data type */
63
#define A(n) {n,ptsData,ptsData,ptsData}        /* attribute */
64
65
/* Define the syntax of all tags. */
66
static const px_tag_syntax_t tag_syntax[256] = {
67
/*0x*/
68
    I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I,
69
/*1x*/
70
    I, I, I, I, I, I, I, I, I, I, I, {2, 0, 0, 0}, I, I, I, I,
71
/*2x*/
72
    I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I,
73
/*3x*/
74
    I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I,
75
/*4x*/
76
    {2, 0, ptsInSession | N, 0},
77
    {1, 0, ptsInSession | N, ptsInSession},
78
    {1, ptsInSession, ptsInSession | ptsInPage | N, ptsInSession},
79
    {1, ptsInSession, ptsInSession | ptsInPage | N, ptsInPage},
80
    {1, ptsInPage, ptsInPage | N, ptsInPage},
81
    P, {1, 1, 1, 0}, C,
82
    C, C, P, P, P, P, P, R(0, 0, ptsReadingFont),
83
/*5x*/
84
    R(0, ptsReadingFont, 0),
85
    R(0, ptsReadingFont, ptsReadingFont),
86
    R(0, 0, ptsReadingChar),
87
    R(0, ptsReadingChar, 0),
88
    R(0, ptsReadingChar, ptsReadingChar),
89
    C, P, P,
90
    P, P, P,
91
    {1, ptsInSession, ptsInSession | ptsExecStream | N, ptsReadingStream},
92
    {1, ptsInSession | ptsReadingStream, ptsInSession | ptsExecStream | N, 0},
93
    {1, ptsInSession | ptsReadingStream, ptsInSession | ptsExecStream | N,
94
     ptsReadingStream},
95
    {1, ptsInSession, ptsInSession | ptsReadingStream | N, 0},
96
    P,
97
/*6x*/
98
    P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P,
99
/*7x*/
100
    P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P,
101
/*8x*/
102
    P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P,
103
/*9x*/
104
    P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P,
105
/*ax*/
106
    P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P,
107
/*bx*/
108
    R(ptsInPage, 0, ptsReadingImage),
109
    R(ptsInPage, ptsReadingImage, 0),
110
    R(ptsInPage, ptsReadingImage, ptsReadingImage),
111
    R(ptsInPage, 0, ptsReadingRastPattern),
112
    R(ptsInPage, ptsReadingRastPattern, 0),
113
    R(ptsInPage, ptsReadingRastPattern, ptsReadingRastPattern),
114
    R(ptsInPage, 0, ptsReadingScan),
115
    P,
116
    R(ptsInPage, ptsReadingScan, ptsReadingScan),
117
    R(ptsInPage, ptsReadingScan, 0),
118
    P, P, P, P, P, P,
119
/*cx*/
120
    D(2), D(3), D(5), D(3), D(5), D(5), DI, DI,
121
    D(3), D(3), D(3), D(3), D(3), D(3), DI, DI,
122
/*dx*/
123
    D(3), D(5), D(9), D(5), D(9), D(9), DI, DI,
124
    DI, DI, DI, DI, DI, DI, DI, DI,
125
/*ex*/
126
    D(5), D(9), D(17), D(9), D(17), D(17), DI, DI,
127
    DI, DI, DI, DI, DI, DI, DI, DI,
128
/*fx*/
129
    I, I, I, I, I, I, I, I,
130
    A(2), A(3), {5, 0, 0, 0}, {2, 0, 0, 0}, I, I, I, I
131
};
132
#undef I
133
#undef P
134
#undef C
135
#undef R
136
#undef D
137
#undef DI
138
#undef A
139
140
/* Allocate a parser state. */
141
px_parser_state_t *
142
px_process_alloc(gs_memory_t * memory)
143
16.0k
{
144
16.0k
    px_parser_state_t *st = (px_parser_state_t *) gs_alloc_bytes(memory,
145
16.0k
                                                                 sizeof
146
16.0k
                                                                 (px_parser_state_t),
147
16.0k
                                                                 "px_process_alloc");
148
149
16.0k
    if (st == 0)
150
0
        return 0;
151
16.0k
    st->memory = memory;
152
16.0k
    px_process_init(st, true);
153
16.0k
    return st;
154
16.0k
}
155
156
/* Release a parser state. */
157
void
158
px_process_release(px_parser_state_t * st)
159
16.0k
{
160
16.0k
    gs_free_object(st->memory, st, "px_process_alloc");
161
16.0k
}
162
163
/* Initialize the parser state. */
164
void
165
px_process_init(px_parser_state_t * st, bool big_endian)
166
36.1k
{
167
36.1k
    st->big_endian = big_endian;
168
36.1k
    st->operator_count = 0;
169
36.1k
    st->parent_operator_count = 0;
170
36.1k
    st->last_operator = pxtNull;
171
36.1k
    st->saved_count = 0;
172
36.1k
    st->data_left = 0;
173
36.1k
    st->macro_state = ptsInitial;
174
36.1k
    st->stack_count = 0;
175
36.1k
    st->data_proc = 0;
176
36.1k
    {
177
36.1k
        int i;
178
179
758k
        for (i = 0; i < max_px_args; ++i)
180
722k
            st->args.pv[i] = 0;
181
36.1k
    }
182
36.1k
    st->args.parser = 0;        /* for garbage collector */
183
36.1k
    memset(st->attribute_indices, 0, px_attribute_next);
184
36.1k
}
185
186
/* Get numeric values from the input. */
187
45.2k
#define get_uint16(st, p) uint16at(p, st->big_endian)
188
85.6k
#define get_sint16(st, p) sint16at(p, st->big_endian)
189
3.68k
#define get_uint32(st, p) uint32at(p, st->big_endian)
190
79
#define get_sint32(st, p) sint32at(p, st->big_endian)
191
2.68k
#define get_real32(st, p) real32at(p, st->big_endian)
192
193
/* Move an array to the heap for persistence if needed. */
194
/* See pxoper.h for details. */
195
static int
196
px_save_array(px_value_t * pv, px_state_t * pxs, client_name_t cname,
197
              uint nbytes)
198
714
{
199
714
    if (pv->type & pxd_on_heap) {       /* Turn off the "on heap" bit, to prevent freeing. */
200
0
        pv->type &= ~pxd_on_heap;
201
714
    } else {                    /* Allocate a heap copy.  Only the first nbytes bytes */
202
        /* of the data are valid. */
203
714
        uint num_elements = pv->value.array.size;
204
714
        uint elt_size = value_size(pv);
205
714
        byte *copy = gs_alloc_byte_array(pxs->memory, num_elements,
206
714
                                         elt_size, cname);
207
208
714
        if (copy == 0)
209
0
            return_error(errorInsufficientMemory);
210
714
        memcpy(copy, pv->value.array.data, nbytes);
211
714
        pv->value.array.data = copy;
212
714
    }
213
714
    return 0;
214
714
}
215
216
/* Clear the stack and the attribute indices, */
217
/* and free heap-allocated arrays. */
218
#define clear_stack()\
219
233k
        for ( ; sp > st->stack; --sp )\
220
121k
          { if ( sp->type & pxd_on_heap )\
221
121k
              gs_free_object(memory, (void *)sp->value.array.data,\
222
121k
                             "px stack pop");\
223
121k
            st->attribute_indices[sp->attribute] = 0;\
224
121k
          }
225
226
/* Define data tracing if debugging. */
227
#ifdef DEBUG
228
#  define trace_data(mem, format, cast, ptr, count)\
229
                  do\
230
                    { uint i_;\
231
                      for ( i_ = 0; i_ < count; ++i_ )\
232
                        dmprintf1(mem, format, (cast)((ptr)[i_]));\
233
                      dmputc(mem, '\n');\
234
                    }\
235
                  while (0)
236
static void
237
trace_array_data(const gs_memory_t * mem, const char *label,
238
                 const px_value_t * pav)
239
{
240
    px_data_type_t type = pav->type;
241
    const byte *ptr = pav->value.array.data;
242
    uint count = pav->value.array.size;
243
    bool big_endian = (type & pxd_big_endian) != 0;
244
    bool text = (type & pxd_ubyte) != 0;
245
    uint i;
246
247
    dmputs(mem, label);
248
    dmputs(mem, (type & pxd_ubyte ? " <" : " {"));
249
    for (i = 0; i < count; ++i) {
250
        if (!(i & 15) && i) {
251
            const char *p;
252
253
            dmputs(mem, "\n  ");
254
            for (p = label; *p; ++p)
255
                dmputc(mem, ' ');
256
        }
257
        if (type & pxd_ubyte) {
258
            dmprintf1(mem, "%02x ", ptr[i]);
259
            if (ptr[i] < 32 || ptr[i] > 126)
260
                text = false;
261
        } else if (type & pxd_uint16)
262
            dmprintf1(mem, "%u ", uint16at(ptr + i * 2, big_endian));
263
        else if (type & pxd_sint16)
264
            dmprintf1(mem, "%d ", sint16at(ptr + i * 2, big_endian));
265
        else if (type & pxd_uint32)
266
            dmprintf1(mem, "%lu ", (ulong) uint32at(ptr + i * 4, big_endian));
267
        else if (type & pxd_sint32)
268
            dmprintf1(mem, "%ld ", (long)sint32at(ptr + i * 4, big_endian));
269
        else if (type & pxd_real32)
270
            dmprintf1(mem, "%g ", real32at(ptr + i * 4, big_endian));
271
        else
272
            dmputs(mem, "? ");
273
    }
274
    dmputs(mem, (type & pxd_ubyte ? ">\n" : "}\n"));
275
    if (text) {
276
        dmputs(mem, "%chars: \"");
277
        debug_print_string(mem, ptr, count);
278
        dmputs(mem, "\"\n");
279
    }
280
}
281
#  define trace_array(mem,pav)\
282
     if ( gs_debug_c('I') )\
283
       trace_array_data(mem,"array:", pav)
284
#else
285
#  define trace_data(mem, format, cast, ptr, count) DO_NOTHING
286
13.2k
#  define trace_array(mem,pav) DO_NOTHING
287
#endif
288
289
/* Process a buffer of PCL XL commands. */
290
int
291
px_process(px_parser_state_t * st, /* lgtm [cpp/use-of-goto] */
292
           px_state_t * pxs, stream_cursor_read * pr)
293
7.06k
{
294
7.06k
    const byte *orig_p = pr->ptr;
295
7.06k
    const byte *next_p = orig_p;        /* start of data not copied to saved */
296
7.06k
    const byte *p;
297
7.06k
    const byte *rlimit;
298
7.06k
    px_value_t *sp = &st->stack[st->stack_count];
299
300
124k
#define stack_limit &st->stack[max_stack - 1]
301
7.06k
    gs_memory_t *memory = st->memory;
302
7.06k
    int code = 0;
303
7.06k
    uint left;
304
7.06k
    uint min_left;
305
7.06k
    px_tag_t tag;
306
7.06k
    const px_tag_syntax_t *syntax = 0;
307
308
7.06k
    st->args.parser = st;
309
7.06k
    st->parent_operator_count = 0;      /* in case of error */
310
    /* Check for leftover data from the previous call. */
311
7.21k
  parse:if (st->saved_count) { /* Fill up the saved buffer so we can make progress. */
312
216
        int move = min(sizeof(st->saved) - st->saved_count,
313
216
                       pr->limit - next_p);
314
315
216
        memcpy(&st->saved[st->saved_count], next_p + 1, move);
316
216
        next_p += move;
317
216
        p = st->saved - 1;
318
216
        rlimit = p + st->saved_count + move;
319
7.00k
    } else {                    /* No leftover data, just read from the input. */
320
7.00k
        p = next_p;
321
7.00k
        rlimit = pr->limit;
322
7.00k
    }
323
37.9k
  top:if (st->data_left) {     /* We're in the middle of reading an array or data block. */
324
15.8k
        if (st->data_proc) {    /* This is a data block. */
325
15.6k
            uint avail = min(rlimit - p, st->data_left);
326
15.6k
            uint used;
327
328
15.6k
            st->args.source.available = avail;
329
15.6k
            st->args.source.data = p + 1;
330
15.6k
            code = (*st->data_proc) (&st->args, pxs);
331
            /* If we get a 'remap_color' error, it means we are dealing with a
332
             * pattern, and the device supports high level patterns. So we must
333
             * use our high level pattern implementation.
334
             */
335
15.6k
            if (code == gs_error_Remap_Color) {
336
0
                code = px_high_level_pattern(pxs->pgs);
337
0
                code = (*st->data_proc) (&st->args, pxs);
338
0
            }
339
15.6k
            used = st->args.source.data - (p + 1);
340
#ifdef DEBUG
341
            if (gs_debug_c('I')) {
342
                px_value_t data_array;
343
344
                data_array.type = pxd_ubyte;
345
                data_array.value.array.data = p + 1;
346
                data_array.value.array.size = used;
347
                trace_array_data(pxs->memory, "data:", &data_array);
348
            }
349
#endif
350
15.6k
            p = st->args.source.data - 1;
351
15.6k
            st->data_left -= used;
352
15.6k
            if (code < 0) {
353
56
                st->args.source.position = 0;
354
56
                goto x;
355
15.5k
            } else if ((code == pxNeedData)
356
15.1k
                       || (code == pxPassThrough && st->data_left != 0)) {
357
455
                code = 0;       /* exit for more data */
358
455
                goto x;
359
15.1k
            } else {
360
15.1k
                st->args.source.position = 0;
361
15.1k
                st->data_proc = 0;
362
15.1k
                if (st->data_left != 0) {
363
92
                    code = gs_note_error(errorExtraData);
364
92
                    goto x;
365
92
                }
366
15.0k
                clear_stack();
367
15.0k
            }
368
15.6k
        } else {                /* This is an array. */
369
185
            uint size = sp->value.array.size;
370
185
            uint scale = value_size(sp);
371
185
            uint nbytes = size * scale;
372
185
            byte *dest =
373
185
                (byte *) sp->value.array.data + nbytes - st->data_left;
374
375
185
            left = rlimit - p;
376
185
            if (left < st->data_left) { /* We still don't have enough data to fill the array. */
377
31
                memcpy(dest, p + 1, left);
378
31
                st->data_left -= left;
379
31
                p = rlimit;
380
31
                code = 0;
381
31
                goto x;
382
31
            }
383
            /* Complete the array and continue parsing. */
384
154
            memcpy(dest, p + 1, st->data_left);
385
154
            trace_array(memory, sp);
386
154
            p += st->data_left;
387
154
        }
388
15.1k
        st->data_left = 0;
389
22.1k
    } else if (st->data_proc) { /* An operator is awaiting data. */
390
        /* Skip white space until we find some. */
391
15.4k
        code = 0;               /* in case we exit */
392
        /* special case - VendorUnique has a length attribute which
393
           we've already parsed and error checked */
394
15.4k
        if (st->data_proc == pxVendorUnique) {
395
0
            st->data_left =
396
0
                st->stack[st->attribute_indices[pxaVUDataLength]].value.i;
397
0
            goto top;
398
15.4k
        } else {
399
15.5k
            while ((left = rlimit - p) != 0) {
400
15.5k
                switch ((tag = p[1])) {
401
148
                case pxtNull:
402
149
                case pxtHT:
403
150
                case pxtLF:
404
151
                case pxtVT:
405
152
                case pxtFF:
406
152
                case pxtCR:
407
152
                    ++p;
408
152
                    continue;
409
1.17k
                case pxt_dataLength:
410
1.17k
                    if (left < 5)
411
0
                        goto x; /* can't look ahead */
412
1.17k
                    st->data_left = get_uint32(st, p + 2);
413
1.17k
                    if_debug2m('i', memory, "tag=  0x%2x  data, length %u\n",
414
1.17k
                               p[1], st->data_left);
415
1.17k
                    p += 5;
416
1.17k
                    goto top;
417
14.1k
                case pxt_dataLengthByte:
418
14.1k
                    if (left < 2)
419
37
                        goto x; /* can't look ahead */
420
14.1k
                    st->data_left = p[2];
421
14.1k
                    if_debug2m('i', memory, "tag=  0x%2x  data, length %u\n",
422
14.1k
                               p[1], st->data_left);
423
14.1k
                    p += 2;
424
14.1k
                    goto top;
425
79
                default:
426
79
                    {
427
79
                        code = gs_note_error(errorMissingData);
428
79
                        goto x;
429
14.1k
                    }
430
15.5k
                }
431
15.5k
            }
432
15.4k
        }
433
15.4k
    }
434
21.8k
    st->args.source.position = 0;
435
21.8k
    st->args.source.available = 0;
436
403k
    while ((left = rlimit - p) != 0 &&
437
403k
           left >= (min_left = (syntax = &tag_syntax[tag = p[1]])->min_input)
438
402k
        ) {
439
402k
        int count;
440
441
#ifdef DEBUG
442
        if (gs_debug_c('i')) {
443
            dmprintf1(memory, "tag=  0x%02x  ", tag);
444
            if (tag == pxt_attr_ubyte || tag == pxt_attr_uint16) {
445
                px_attribute_t attr =
446
                    (tag == pxt_attr_ubyte ? p[2] : get_uint16(st, p + 2));
447
                const char *aname = px_attribute_names[attr];
448
449
                if (aname)
450
                    dmprintf1(memory, "   @%s\n", aname);
451
                else
452
                    dmprintf1(memory, "   attribute %u ???\n", attr);
453
            } else {
454
                const char *format;
455
                const char *tname;
456
                bool operator = false;
457
458
                if (tag < 0x40)
459
                    format = "%s\n", tname = px_tag_0_names[tag];
460
                else if (tag < 0xc0)
461
                    format = "%s", tname = px_operator_names[tag - 0x40],
462
                        operator = true;
463
                else {
464
                    tname = px_tag_c0_names[tag - 0xc0];
465
                    if (tag < 0xf0)
466
                        format = "      %s";    /* data values follow */
467
                    else
468
                        format = "%s\n";
469
                }
470
                if (tname) {
471
                    dmprintf1(memory, format, tname);
472
                    if (operator)
473
                        dmprintf1(memory, " (%ld)\n", st->operator_count + 1);
474
                } else
475
                    dmputs(memory, "???\n");
476
            }
477
        }
478
#endif
479
402k
        if ((st->macro_state & syntax->state_mask) != syntax->state_value) {
480
            /*
481
             * We should probably distinguish here between
482
             * out-of-context operators and illegal tags, but it's too
483
             * much trouble.
484
             */
485
1.13k
            code = gs_note_error(errorIllegalOperatorSequence);
486
1.13k
            if (tag >= 0x40 && tag < 0xc0)
487
860
                st->last_operator = tag;
488
1.13k
            goto x;
489
1.13k
        }
490
401k
        st->macro_state ^= syntax->state_transition;
491
401k
        switch (tag >> 3) {
492
36.2k
            case 0:
493
36.2k
                switch (tag) {
494
36.0k
                    case pxtNull:
495
36.0k
                        ++p;
496
36.0k
                        continue;
497
223
                    default:
498
223
                        break;
499
36.2k
                }
500
223
                break;
501
737
            case 1:
502
737
                switch (tag) {
503
230
                    case pxtHT:
504
475
                    case pxtLF:
505
488
                    case pxtVT:
506
548
                    case pxtFF:
507
706
                    case pxtCR:
508
706
                        ++p;
509
706
                        continue;
510
31
                    default:
511
31
                        break;
512
737
                }
513
31
                break;
514
2.80k
            case 3:
515
2.80k
                if (tag == pxt1b) {     /* ESC *//* Check for UEL */
516
2.78k
                    if (memcmp(p + 1, "\033%-12345X", min(left, 9)))
517
463
                        break;  /* not UEL, error */
518
2.32k
                    if (left < 9)
519
4
                        goto x; /* need more data */
520
2.31k
                    p += 9;
521
2.31k
                    code = e_ExitLanguage;
522
2.31k
                    goto x;
523
2.32k
                }
524
22
                break;
525
582
            case 4:
526
582
                switch (tag) {
527
298
                    case pxtSpace:
528
                        /* break; will error, compatible with lj */
529
                        /* ++p;continue; silently ignores the space */
530
298
                        ++p;
531
298
                        continue;
532
284
                    default:
533
284
                        break;
534
582
                }
535
284
                break;
536
5.37k
            case 8:
537
8.54k
            case 9:
538
11.4k
            case 10:
539
11.7k
            case 11:
540
25.1k
            case 12:
541
46.7k
            case 13:
542
50.6k
            case 14:
543
59.9k
            case 15:
544
87.5k
            case 16:
545
87.5k
            case 17:
546
96.1k
            case 18:
547
107k
            case 19:
548
109k
            case 20:
549
112k
            case 21:
550
113k
            case 22:
551
113k
            case 23:
552
                /* Operators */
553
                /* Make sure that we have all the required attributes, */
554
                /* and no attributes that are neither required nor */
555
                /* optional.  (It's up to the operator to make any */
556
                /* more precise checks than this. */
557
113k
                st->operator_count++;
558
                /* if this is a passthrough operator we have to tell
559
                   the passthrough module if this operator was
560
                   preceded by another passthrough operator or a
561
                   different xl operator */
562
113k
                if (tag == pxtPassThrough) {
563
52
                    pxpcl_passthroughcontiguous(pxs, st->last_operator == tag);
564
113k
                } else if (st->last_operator == pxtPassThrough) {
565
0
                    pxpcl_endpassthroughcontiguous(pxs);
566
0
                }
567
568
113k
                st->last_operator = tag;
569
113k
                {
570
113k
                    const px_operator_definition_t *pod =
571
113k
                        &px_operator_definitions[tag - 0x40];
572
113k
                    int left = sp - st->stack;
573
113k
                    const byte /*px_attribute_t */  * pal = pod->attrs;
574
113k
                    px_value_t **ppv = st->args.pv;
575
113k
                    bool required = true;
576
113k
                    code = 0;
577
                    /*
578
                     * Scan the attributes.  Illegal attributes take priority
579
                     * over missing attributes, which in turn take priority
580
                     * over illegal data types.
581
                     */
582
557k
                    for (;; ++pal, ++ppv) {
583
557k
                        px_attribute_t attr = *pal;
584
557k
                        uint index;
585
586
557k
                        if (!attr) {    /*
587
                                         * We've reached the end of either the required or
588
                                         * the optional attribute list.
589
                                         */
590
227k
                            if (!required)
591
113k
                                break;
592
113k
                            required = false;
593
113k
                            --ppv;      /* cancel incrementing */
594
113k
                            continue;
595
227k
                        }
596
330k
                        if ((index = st->attribute_indices[attr]) == 0) {
597
208k
                            if (required)
598
127
                                code = gs_note_error(errorMissingAttribute);
599
208k
                            else
600
208k
                                *ppv = 0;
601
208k
                        } else {        /* Check the attribute data type and value. */
602
122k
                            px_value_t *pv = *ppv = &st->stack[index];
603
122k
                            const px_attr_value_type_t *pavt =
604
122k
                                &px_attr_value_types[attr];
605
122k
                            int acode;
606
607
122k
                            if ((~pavt->mask & pv->type &
608
122k
                                 (pxd_structure | pxd_representation)) ||
609
121k
                                (pavt->mask == (pxd_scalar | pxd_ubyte) &&
610
50.1k
                                 (pv->value.i < 0
611
50.1k
                                  || pv->value.i > pavt->limit))
612
122k
                                ) {
613
51
                                if (code >= 0)
614
50
                                    code =
615
50
                                        gs_note_error
616
51
                                        (errorIllegalAttributeDataType);
617
51
                            }
618
122k
                            if (pavt->proc != 0
619
16.0k
                                && (acode = (*pavt->proc) (pv)) < 0) {
620
8
                                if (code >= 0)
621
5
                                    code = acode;
622
8
                            }
623
122k
                            --left;
624
122k
                        }
625
330k
                    }
626
627
                    /* Make sure there are no attributes left over. */
628
113k
                    if (left)
629
99
                        code = gs_note_error(errorIllegalAttribute);
630
113k
                    if (code >= 0) {
631
113k
                        st->args.source.phase = 0;
632
113k
                        code = (*pod->proc) (&st->args, pxs);
633
                        /* If we get a 'remap_color' error, it means we are dealing with a
634
                         * pattern, and the device supports high level patterns. So we must
635
                         * use our high level pattern implementation.
636
                         */
637
113k
                        if (code == gs_error_Remap_Color) {
638
0
                            code = px_high_level_pattern(pxs->pgs);
639
0
                            if (code < 0)
640
0
                                goto x;
641
0
                            code = (*pod->proc) (&st->args, pxs);
642
0
                        }
643
113k
                    }
644
113k
                    if (code < 0)
645
523
                        goto x;
646
                    /* Check whether the operator wanted source data. */
647
112k
                    if (code == pxNeedData) {
648
15.3k
                        if (!pxs->data_source_open) {
649
0
                            code = gs_note_error(errorDataSourceNotOpen);
650
0
                            goto x;
651
0
                        }
652
15.3k
                        st->data_proc = pod->proc;
653
15.3k
                        ++p;
654
15.3k
                        goto top;
655
15.3k
                    }
656
112k
                }
657
97.5k
                clear_stack();
658
97.5k
                ++p;
659
97.5k
                continue;
660
81.9k
            case 24:
661
81.9k
                sp[1].type = pxd_scalar;
662
81.9k
                count = 1;
663
81.9k
                goto data;
664
26.1k
            case 26:
665
26.1k
                sp[1].type = pxd_xy;
666
26.1k
                count = 2;
667
26.1k
                goto data;
668
2.66k
            case 28:
669
2.66k
                sp[1].type = pxd_box;
670
2.66k
                count = 4;
671
2.66k
                goto data;
672
                /* Scalar, point, and box data */
673
110k
              data:{
674
110k
                    int i;
675
676
110k
                    if (sp == stack_limit) {
677
0
                        code = gs_note_error(errorInternalOverflow);
678
0
                        goto x;
679
0
                    }
680
110k
                    ++sp;
681
110k
                    sp->attribute = 0;
682
110k
                    p += 2;
683
#ifdef DEBUG
684
#  define trace_scalar(mem, format, cast, alt)\
685
                  if ( gs_debug_c('i') )\
686
                    trace_data(mem, format, cast, sp->value.alt, count)
687
#else
688
110k
#  define trace_scalar(mem, format, cast, alt) DO_NOTHING
689
110k
#endif
690
110k
                    switch (tag & 7) {
691
65.2k
                        case pxt_ubyte & 7:
692
65.2k
                            sp->type |= pxd_ubyte;
693
130k
                            for (i = 0; i < count; ++p, ++i)
694
65.2k
                                sp->value.ia[i] = *p;
695
80.4k
                          dux:trace_scalar(pxs->memory, " %lu", ulong,
696
80.4k
                                         ia);
697
80.4k
                            --p;
698
80.4k
                            continue;
699
13.9k
                        case pxt_uint16 & 7:
700
13.9k
                            sp->type |= pxd_uint16;
701
34.1k
                            for (i = 0; i < count; p += 2, ++i)
702
20.2k
                                sp->value.ia[i] = get_uint16(st, p);
703
13.9k
                            goto dux;
704
1.25k
                        case pxt_uint32 & 7:
705
1.25k
                            sp->type |= pxd_uint32;
706
2.51k
                            for (i = 0; i < count; p += 4, ++i)
707
1.25k
                                sp->value.ia[i] = get_uint32(st, p);
708
1.25k
                            goto dux;
709
29.0k
                        case pxt_sint16 & 7:
710
29.0k
                            sp->type |= pxd_sint16;
711
85.6k
                            for (i = 0; i < count; p += 2, ++i)
712
56.5k
                                sp->value.ia[i] = get_sint16(st, p);
713
29.0k
                          dsx:trace_scalar(pxs->memory, " %ld", long,
714
29.0k
                                         ia);
715
29.0k
                            --p;
716
29.0k
                            continue;
717
27
                        case pxt_sint32 & 7:
718
27
                            sp->type |= pxd_sint32;
719
79
                            for (i = 0; i < count; p += 4, ++i)
720
52
                                sp->value.ia[i] = get_sint32(st, p);
721
27
                            goto dsx;
722
1.20k
                        case pxt_real32 & 7:
723
1.20k
                            sp->type |= pxd_real32;
724
2.68k
                            for (i = 0; i < count; p += 4, ++i)
725
1.47k
                                sp->value.ra[i] = get_real32(st, p);
726
1.20k
                            trace_scalar(pxs->memory, " %g", double, ra);
727
728
1.20k
                            --p;
729
1.20k
                            continue;
730
10
                        default:
731
10
                            break;
732
110k
                    }
733
110k
                }
734
10
                break;
735
13.3k
            case 25:
736
                /* Array data */
737
13.3k
                {
738
13.3k
                    const byte *dp;
739
13.3k
                    uint nbytes;
740
741
13.3k
                    if (sp == stack_limit) {
742
0
                        code = gs_note_error(errorInternalOverflow);
743
0
                        goto x;
744
0
                    }
745
13.3k
                    switch (p[2]) {
746
2.17k
                        case pxt_ubyte:
747
2.17k
                            sp[1].value.array.size = p[3];
748
2.17k
                            dp = p + 4;
749
2.17k
                            break;
750
11.1k
                        case pxt_uint16:
751
11.1k
                            if (left < 4) {
752
9
                                if_debug0m('i', memory, "...\n");
753
                                /* Undo the state transition. */
754
9
                                st->macro_state ^= syntax->state_transition;
755
9
                                goto x;
756
9
                            }
757
11.1k
                            sp[1].value.array.size = get_uint16(st, p + 3);
758
11.1k
                            dp = p + 5;
759
11.1k
                            break;
760
49
                        default:
761
49
                            st->last_operator = tag;    /* for error message */
762
49
                            code = gs_note_error(errorIllegalTag);
763
49
                            goto x;
764
13.3k
                    }
765
13.2k
                    nbytes = sp[1].value.array.size;
766
13.2k
                    if_debug1m('i', memory, "[%u]\n", sp[1].value.array.size);
767
13.2k
                    switch (tag) {
768
13.2k
                        case pxt_ubyte_array:
769
13.2k
                            sp[1].type = pxd_array | pxd_ubyte;
770
13.2k
                          array:++sp;
771
13.2k
                            if (st->big_endian)
772
0
                                sp->type |= pxd_big_endian;
773
13.2k
                            sp->value.array.data = dp;
774
13.2k
                            sp->attribute = 0;
775
                            /* Check whether we have enough data for the entire */
776
                            /* array. */
777
13.2k
                            if (rlimit + 1 - dp < nbytes) {     /* Exit now, continue reading when we return. */
778
226
                                uint avail = rlimit + 1 - dp;
779
780
226
                                code = px_save_array(sp, pxs, "partial array",
781
226
                                                     avail);
782
226
                                if (code < 0)
783
0
                                    goto x;
784
226
                                sp->type |= pxd_on_heap;
785
226
                                st->data_left = nbytes - avail;
786
226
                                st->data_proc = 0;
787
226
                                p = rlimit;
788
226
                                goto x;
789
226
                            }
790
13.0k
                            p = dp + nbytes - 1;
791
13.0k
                            trace_array(memory, sp);
792
13.0k
                            continue;
793
1
                        case pxt_uint16_array:
794
1
                            sp[1].type = pxd_array | pxd_uint16;
795
4
                          a16:nbytes <<= 1;
796
4
                            goto array;
797
2
                        case pxt_uint32_array:
798
2
                            sp[1].type = pxd_array | pxd_uint32;
799
4
                          a32:nbytes <<= 2;
800
4
                            goto array;
801
3
                        case pxt_sint16_array:
802
3
                            sp[1].type = pxd_array | pxd_sint16;
803
3
                            goto a16;
804
1
                        case pxt_sint32_array:
805
1
                            sp[1].type = pxd_array | pxd_sint32;
806
1
                            goto a32;
807
1
                        case pxt_real32_array:
808
1
                            sp[1].type = pxd_array | pxd_real32;
809
1
                            goto a32;
810
2
                        default:
811
2
                            break;
812
13.2k
                    }
813
2
                    break;
814
13.2k
                }
815
2
                break;
816
123k
            case 31:
817
123k
                {
818
123k
                    px_attribute_t attr;
819
123k
                    const byte *pnext;
820
821
123k
                    switch (tag) {
822
123k
                        case pxt_attr_ubyte:
823
123k
                            attr = p[2];
824
123k
                            pnext = p + 2;
825
123k
                            goto a;
826
1
                        case pxt_attr_uint16:
827
1
                            attr = get_uint16(st, p + 2);
828
1
                            pnext = p + 3;
829
123k
                          a:if (attr >=
830
123k
                                px_attribute_next)
831
106
                                break;
832
                            /*
833
                             * We could check the attribute value type here, but
834
                             * in order to match the behavior of the H-P printers,
835
                             * we don't do it until we see the operator.
836
                             *
837
                             * It is legal to specify the same attribute more than
838
                             * once; the last value has priority.  If this happens,
839
                             * since the order of attributes doesn't matter, we can
840
                             * just replace the former value on the stack.
841
                             */
842
122k
                            sp->attribute = attr;
843
122k
                            if (st->attribute_indices[attr] != 0) {
844
10
                                px_value_t *old_sp =
845
10
                                    &st->stack[st->attribute_indices[attr]];
846
                                /* If the old value is on the heap, free it. */
847
10
                                if (old_sp->type & pxd_on_heap)
848
0
                                    gs_free_object(memory,
849
10
                                                   (void *)old_sp->value.
850
10
                                                   array.data,
851
10
                                                   "old value for duplicate attribute");
852
10
                                *old_sp = *sp--;
853
10
                            } else
854
122k
                                st->attribute_indices[attr] = sp - st->stack;
855
122k
                            p = pnext;
856
122k
                            continue;
857
38
                        case pxt_dataLength:
858
                            /*
859
                             * Unexpected data length operators are normally not
860
                             * allowed, but there might be a zero-length data
861
                             * block immediately following a zero-size image,
862
                             * which doesn't ask for any data.
863
                             */
864
38
                            if (uint32at(p + 2, true /*arbitrary */ ) == 0) {
865
1
                                p += 5;
866
1
                                continue;
867
1
                            }
868
37
                            break;
869
37
                        case pxt_dataLengthByte:
870
                            /* See the comment under pxt_dataLength above. */
871
30
                            if (p[2] == 0) {
872
20
                                p += 2;
873
20
                                continue;
874
20
                            }
875
10
                            break;
876
216
                        default:
877
216
                            break;
878
123k
                    }
879
123k
                }
880
369
                break;
881
483
            default:
882
483
                break;
883
401k
        }
884
        /* Unknown tag value.  Report an error. */
885
1.88k
        st->last_operator = tag;        /* for error message */
886
1.88k
        code = gs_note_error(errorIllegalTag);
887
1.88k
        break;
888
401k
    }
889
7.21k
  x:                           /* Save any leftover input. */
890
7.21k
    left = rlimit - p;
891
7.21k
    if (rlimit != pr->limit) {  /* We were reading saved input. */
892
216
        if (left <= next_p - orig_p) {  /* We finished reading the previously saved input. */
893
            /* Continue reading current input, unless we got an error. */
894
211
            p = next_p -= left;
895
211
            rlimit = pr->limit;
896
211
            st->saved_count = 0;
897
211
            if (code >= 0)
898
152
                goto parse;
899
211
        } else {                /* There's still some previously saved input left over. */
900
5
            memmove(st->saved, p + 1, st->saved_count = left);
901
5
            p = next_p;
902
5
            rlimit = pr->limit;
903
5
            left = rlimit - p;
904
5
        }
905
216
    }
906
    /* Except in case of error, save any remaining input. */
907
7.06k
    if (code >= 0) {
908
932
        if (left + st->saved_count > sizeof(st->saved)) {       /* Fatal error -- shouldn't happen! */
909
19
            code = gs_note_error(errorInternalOverflow);
910
19
            st->saved_count = 0;
911
913
        } else {
912
913
            memcpy(&st->saved[st->saved_count], p + 1, left);
913
913
            st->saved_count += left;
914
913
            p = rlimit;
915
913
        }
916
932
    }
917
7.06k
    pr->ptr = p;
918
7.06k
    st->stack_count = sp - st->stack;
919
    /* Move to the heap any arrays whose data was being referenced */
920
    /* directly in the input buffer. */
921
10.7k
    for (; sp > st->stack; --sp)
922
3.71k
        if ((sp->type & (pxd_array | pxd_on_heap)) == pxd_array) {
923
488
            int code = px_save_array(sp, pxs, "px stack array to heap",
924
488
                                     sp->value.array.size * value_size(sp));
925
926
488
            if (code < 0)
927
0
                break;
928
488
            sp->type |= pxd_on_heap;
929
488
        }
930
7.06k
    if (code < 0 && syntax != 0) {      /* Undo the state transition. */
931
6.14k
        st->macro_state ^= syntax->state_transition;
932
6.14k
    }
933
7.06k
    return code;
934
7.21k
}
935
936
uint
937
px_parser_data_left(px_parser_state_t * pxp)
938
4
{
939
4
    return pxp->data_left;
940
4
}