Coverage Report

Created: 2026-07-24 07:44

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.1k
{
144
16.1k
    px_parser_state_t *st = (px_parser_state_t *) gs_alloc_bytes(memory,
145
16.1k
                                                                 sizeof
146
16.1k
                                                                 (px_parser_state_t),
147
16.1k
                                                                 "px_process_alloc");
148
149
16.1k
    if (st == 0)
150
0
        return 0;
151
16.1k
    st->memory = memory;
152
16.1k
    px_process_init(st, true);
153
16.1k
    return st;
154
16.1k
}
155
156
/* Release a parser state. */
157
void
158
px_process_release(px_parser_state_t * st)
159
16.1k
{
160
16.1k
    gs_free_object(st->memory, st, "px_process_alloc");
161
16.1k
}
162
163
/* Initialize the parser state. */
164
void
165
px_process_init(px_parser_state_t * st, bool big_endian)
166
33.0k
{
167
33.0k
    st->big_endian = big_endian;
168
33.0k
    st->operator_count = 0;
169
33.0k
    st->parent_operator_count = 0;
170
33.0k
    st->last_operator = pxtNull;
171
33.0k
    st->saved_count = 0;
172
33.0k
    st->data_left = 0;
173
33.0k
    st->macro_state = ptsInitial;
174
33.0k
    st->stack_count = 0;
175
33.0k
    st->data_proc = 0;
176
33.0k
    {
177
33.0k
        int i;
178
179
694k
        for (i = 0; i < max_px_args; ++i)
180
661k
            st->args.pv[i] = 0;
181
33.0k
    }
182
33.0k
    st->args.parser = 0;        /* for garbage collector */
183
33.0k
    memset(st->attribute_indices, 0, px_attribute_next);
184
33.0k
}
185
186
/* Get numeric values from the input. */
187
40.3k
#define get_uint16(st, p) uint16at(p, st->big_endian)
188
77.5k
#define get_sint16(st, p) sint16at(p, st->big_endian)
189
3.16k
#define get_uint32(st, p) uint32at(p, st->big_endian)
190
19
#define get_sint32(st, p) sint32at(p, st->big_endian)
191
2.35k
#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
642
{
199
642
    if (pv->type & pxd_on_heap) {       /* Turn off the "on heap" bit, to prevent freeing. */
200
0
        pv->type &= ~pxd_on_heap;
201
642
    } else {                    /* Allocate a heap copy.  Only the first nbytes bytes */
202
        /* of the data are valid. */
203
642
        uint num_elements = pv->value.array.size;
204
642
        uint elt_size = value_size(pv);
205
642
        byte *copy = gs_alloc_byte_array(pxs->memory, num_elements,
206
642
                                         elt_size, cname);
207
208
642
        if (copy == 0)
209
0
            return_error(errorInsufficientMemory);
210
642
        memcpy(copy, pv->value.array.data, nbytes);
211
642
        pv->value.array.data = copy;
212
642
    }
213
642
    return 0;
214
642
}
215
216
/* Clear the stack and the attribute indices, */
217
/* and free heap-allocated arrays. */
218
#define clear_stack()\
219
210k
        for ( ; sp > st->stack; --sp )\
220
108k
          { if ( sp->type & pxd_on_heap )\
221
108k
              gs_free_object(memory, (void *)sp->value.array.data,\
222
108k
                             "px stack pop");\
223
108k
            st->attribute_indices[sp->attribute] = 0;\
224
108k
          }
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
11.7k
#  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
6.01k
{
294
6.01k
    const byte *orig_p = pr->ptr;
295
6.01k
    const byte *next_p = orig_p;        /* start of data not copied to saved */
296
6.01k
    const byte *p;
297
6.01k
    const byte *rlimit;
298
6.01k
    px_value_t *sp = &st->stack[st->stack_count];
299
300
111k
#define stack_limit &st->stack[max_stack - 1]
301
6.01k
    gs_memory_t *memory = st->memory;
302
6.01k
    int code = 0;
303
6.01k
    uint left;
304
6.01k
    uint min_left;
305
6.01k
    px_tag_t tag;
306
6.01k
    const px_tag_syntax_t *syntax = 0;
307
308
6.01k
    st->args.parser = st;
309
6.01k
    st->parent_operator_count = 0;      /* in case of error */
310
    /* Check for leftover data from the previous call. */
311
6.14k
  parse:if (st->saved_count) { /* Fill up the saved buffer so we can make progress. */
312
202
        int move = min(sizeof(st->saved) - st->saved_count,
313
202
                       pr->limit - next_p);
314
315
202
        memcpy(&st->saved[st->saved_count], next_p + 1, move);
316
202
        next_p += move;
317
202
        p = st->saved - 1;
318
202
        rlimit = p + st->saved_count + move;
319
5.94k
    } else {                    /* No leftover data, just read from the input. */
320
5.94k
        p = next_p;
321
5.94k
        rlimit = pr->limit;
322
5.94k
    }
323
34.3k
  top:if (st->data_left) {     /* We're in the middle of reading an array or data block. */
324
14.5k
        if (st->data_proc) {    /* This is a data block. */
325
14.3k
            uint avail = min(rlimit - p, st->data_left);
326
14.3k
            uint used;
327
328
14.3k
            st->args.source.available = avail;
329
14.3k
            st->args.source.data = p + 1;
330
14.3k
            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
14.3k
            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
14.3k
            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
14.3k
            p = st->args.source.data - 1;
351
14.3k
            st->data_left -= used;
352
14.3k
            if (code < 0) {
353
42
                st->args.source.position = 0;
354
42
                goto x;
355
14.3k
            } else if ((code == pxNeedData)
356
13.8k
                       || (code == pxPassThrough && st->data_left != 0)) {
357
420
                code = 0;       /* exit for more data */
358
420
                goto x;
359
13.8k
            } else {
360
13.8k
                st->args.source.position = 0;
361
13.8k
                st->data_proc = 0;
362
13.8k
                if (st->data_left != 0) {
363
91
                    code = gs_note_error(errorExtraData);
364
91
                    goto x;
365
91
                }
366
13.7k
                clear_stack();
367
13.7k
            }
368
14.3k
        } else {                /* This is an array. */
369
164
            uint size = sp->value.array.size;
370
164
            uint scale = value_size(sp);
371
164
            uint nbytes = size * scale;
372
164
            byte *dest =
373
164
                (byte *) sp->value.array.data + nbytes - st->data_left;
374
375
164
            left = rlimit - p;
376
164
            if (left < st->data_left) { /* We still don't have enough data to fill the array. */
377
20
                memcpy(dest, p + 1, left);
378
20
                st->data_left -= left;
379
20
                p = rlimit;
380
20
                code = 0;
381
20
                goto x;
382
20
            }
383
            /* Complete the array and continue parsing. */
384
144
            memcpy(dest, p + 1, st->data_left);
385
144
            trace_array(memory, sp);
386
144
            p += st->data_left;
387
144
        }
388
13.9k
        st->data_left = 0;
389
19.8k
    } else if (st->data_proc) { /* An operator is awaiting data. */
390
        /* Skip white space until we find some. */
391
14.1k
        code = 0;               /* in case we exit */
392
        /* special case - VendorUnique has a length attribute which
393
           we've already parsed and error checked */
394
14.1k
        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
14.1k
        } else {
399
14.3k
            while ((left = rlimit - p) != 0) {
400
14.3k
                switch ((tag = p[1])) {
401
151
                case pxtNull:
402
151
                case pxtHT:
403
152
                case pxtLF:
404
153
                case pxtVT:
405
154
                case pxtFF:
406
154
                case pxtCR:
407
154
                    ++p;
408
154
                    continue;
409
1.09k
                case pxt_dataLength:
410
1.09k
                    if (left < 5)
411
0
                        goto x; /* can't look ahead */
412
1.09k
                    st->data_left = get_uint32(st, p + 2);
413
1.09k
                    if_debug2m('i', memory, "tag=  0x%2x  data, length %u\n",
414
1.09k
                               p[1], st->data_left);
415
1.09k
                    p += 5;
416
1.09k
                    goto top;
417
12.9k
                case pxt_dataLengthByte:
418
12.9k
                    if (left < 2)
419
27
                        goto x; /* can't look ahead */
420
12.9k
                    st->data_left = p[2];
421
12.9k
                    if_debug2m('i', memory, "tag=  0x%2x  data, length %u\n",
422
12.9k
                               p[1], st->data_left);
423
12.9k
                    p += 2;
424
12.9k
                    goto top;
425
71
                default:
426
71
                    {
427
71
                        code = gs_note_error(errorMissingData);
428
71
                        goto x;
429
12.9k
                    }
430
14.3k
                }
431
14.3k
            }
432
14.1k
        }
433
14.1k
    }
434
19.6k
    st->args.source.position = 0;
435
19.6k
    st->args.source.available = 0;
436
388k
    while ((left = rlimit - p) != 0 &&
437
388k
           left >= (min_left = (syntax = &tag_syntax[tag = p[1]])->min_input)
438
388k
        ) {
439
388k
        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
388k
        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.03k
            code = gs_note_error(errorIllegalOperatorSequence);
486
1.03k
            if (tag >= 0x40 && tag < 0xc0)
487
795
                st->last_operator = tag;
488
1.03k
            goto x;
489
1.03k
        }
490
387k
        st->macro_state ^= syntax->state_transition;
491
387k
        switch (tag >> 3) {
492
42.2k
            case 0:
493
42.2k
                switch (tag) {
494
42.0k
                    case pxtNull:
495
42.0k
                        ++p;
496
42.0k
                        continue;
497
170
                    default:
498
170
                        break;
499
42.2k
                }
500
170
                break;
501
379
            case 1:
502
379
                switch (tag) {
503
220
                    case pxtHT:
504
311
                    case pxtLF:
505
317
                    case pxtVT:
506
332
                    case pxtFF:
507
355
                    case pxtCR:
508
355
                        ++p;
509
355
                        continue;
510
24
                    default:
511
24
                        break;
512
379
                }
513
24
                break;
514
2.40k
            case 3:
515
2.40k
                if (tag == pxt1b) {     /* ESC *//* Check for UEL */
516
2.38k
                    if (memcmp(p + 1, "\033%-12345X", min(left, 9)))
517
378
                        break;  /* not UEL, error */
518
2.00k
                    if (left < 9)
519
2
                        goto x; /* need more data */
520
2.00k
                    p += 9;
521
2.00k
                    code = e_ExitLanguage;
522
2.00k
                    goto x;
523
2.00k
                }
524
25
                break;
525
17.2k
            case 4:
526
17.2k
                switch (tag) {
527
17.0k
                    case pxtSpace:
528
                        /* break; will error, compatible with lj */
529
                        /* ++p;continue; silently ignores the space */
530
17.0k
                        ++p;
531
17.0k
                        continue;
532
188
                    default:
533
188
                        break;
534
17.2k
                }
535
188
                break;
536
4.61k
            case 8:
537
7.37k
            case 9:
538
9.75k
            case 10:
539
9.99k
            case 11:
540
22.0k
            case 12:
541
41.5k
            case 13:
542
44.9k
            case 14:
543
53.5k
            case 15:
544
78.7k
            case 16:
545
78.7k
            case 17:
546
86.8k
            case 18:
547
97.5k
            case 19:
548
98.6k
            case 20:
549
101k
            case 21:
550
102k
            case 22:
551
102k
            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
102k
                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
102k
                if (tag == pxtPassThrough) {
563
49
                    pxpcl_passthroughcontiguous(pxs, st->last_operator == tag);
564
102k
                } else if (st->last_operator == pxtPassThrough) {
565
0
                    pxpcl_endpassthroughcontiguous(pxs);
566
0
                }
567
568
102k
                st->last_operator = tag;
569
102k
                {
570
102k
                    const px_operator_definition_t *pod =
571
102k
                        &px_operator_definitions[tag - 0x40];
572
102k
                    int left = sp - st->stack;
573
102k
                    const byte /*px_attribute_t */  * pal = pod->attrs;
574
102k
                    px_value_t **ppv = st->args.pv;
575
102k
                    bool required = true;
576
102k
                    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
503k
                    for (;; ++pal, ++ppv) {
583
503k
                        px_attribute_t attr = *pal;
584
503k
                        uint index;
585
586
503k
                        if (!attr) {    /*
587
                                         * We've reached the end of either the required or
588
                                         * the optional attribute list.
589
                                         */
590
205k
                            if (!required)
591
102k
                                break;
592
102k
                            required = false;
593
102k
                            --ppv;      /* cancel incrementing */
594
102k
                            continue;
595
205k
                        }
596
298k
                        if ((index = st->attribute_indices[attr]) == 0) {
597
188k
                            if (required)
598
131
                                code = gs_note_error(errorMissingAttribute);
599
188k
                            else
600
188k
                                *ppv = 0;
601
188k
                        } else {        /* Check the attribute data type and value. */
602
109k
                            px_value_t *pv = *ppv = &st->stack[index];
603
109k
                            const px_attr_value_type_t *pavt =
604
109k
                                &px_attr_value_types[attr];
605
109k
                            int acode;
606
607
109k
                            if ((~pavt->mask & pv->type &
608
109k
                                 (pxd_structure | pxd_representation)) ||
609
109k
                                (pavt->mask == (pxd_scalar | pxd_ubyte) &&
610
45.0k
                                 (pv->value.i < 0
611
45.0k
                                  || pv->value.i > pavt->limit))
612
109k
                                ) {
613
33
                                if (code >= 0)
614
33
                                    code =
615
33
                                        gs_note_error
616
33
                                        (errorIllegalAttributeDataType);
617
33
                            }
618
109k
                            if (pavt->proc != 0
619
14.1k
                                && (acode = (*pavt->proc) (pv)) < 0) {
620
9
                                if (code >= 0)
621
6
                                    code = acode;
622
9
                            }
623
109k
                            --left;
624
109k
                        }
625
298k
                    }
626
627
                    /* Make sure there are no attributes left over. */
628
102k
                    if (left)
629
101
                        code = gs_note_error(errorIllegalAttribute);
630
102k
                    if (code >= 0) {
631
102k
                        st->args.source.phase = 0;
632
102k
                        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
102k
                        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
102k
                    }
644
102k
                    if (code < 0)
645
429
                        goto x;
646
                    /* Check whether the operator wanted source data. */
647
102k
                    if (code == pxNeedData) {
648
14.1k
                        if (!pxs->data_source_open) {
649
0
                            code = gs_note_error(errorDataSourceNotOpen);
650
0
                            goto x;
651
0
                        }
652
14.1k
                        st->data_proc = pod->proc;
653
14.1k
                        ++p;
654
14.1k
                        goto top;
655
14.1k
                    }
656
102k
                }
657
88.0k
                clear_stack();
658
88.0k
                ++p;
659
88.0k
                continue;
660
73.6k
            case 24:
661
73.6k
                sp[1].type = pxd_scalar;
662
73.6k
                count = 1;
663
73.6k
                goto data;
664
23.7k
            case 26:
665
23.7k
                sp[1].type = pxd_xy;
666
23.7k
                count = 2;
667
23.7k
                goto data;
668
2.33k
            case 28:
669
2.33k
                sp[1].type = pxd_box;
670
2.33k
                count = 4;
671
2.33k
                goto data;
672
                /* Scalar, point, and box data */
673
99.6k
              data:{
674
99.6k
                    int i;
675
676
99.6k
                    if (sp == stack_limit) {
677
0
                        code = gs_note_error(errorInternalOverflow);
678
0
                        goto x;
679
0
                    }
680
99.6k
                    ++sp;
681
99.6k
                    sp->attribute = 0;
682
99.6k
                    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
99.6k
#  define trace_scalar(mem, format, cast, alt) DO_NOTHING
689
99.6k
#endif
690
99.6k
                    switch (tag & 7) {
691
58.7k
                        case pxt_ubyte & 7:
692
58.7k
                            sp->type |= pxd_ubyte;
693
117k
                            for (i = 0; i < count; ++p, ++i)
694
58.7k
                                sp->value.ia[i] = *p;
695
72.2k
                          dux:trace_scalar(pxs->memory, " %lu", ulong,
696
72.2k
                                         ia);
697
72.2k
                            --p;
698
72.2k
                            continue;
699
12.5k
                        case pxt_uint16 & 7:
700
12.5k
                            sp->type |= pxd_uint16;
701
30.5k
                            for (i = 0; i < count; p += 2, ++i)
702
18.0k
                                sp->value.ia[i] = get_uint16(st, p);
703
12.5k
                            goto dux;
704
1.03k
                        case pxt_uint32 & 7:
705
1.03k
                            sp->type |= pxd_uint32;
706
2.06k
                            for (i = 0; i < count; p += 4, ++i)
707
1.03k
                                sp->value.ia[i] = get_uint32(st, p);
708
1.03k
                            goto dux;
709
26.3k
                        case pxt_sint16 & 7:
710
26.3k
                            sp->type |= pxd_sint16;
711
77.5k
                            for (i = 0; i < count; p += 2, ++i)
712
51.2k
                                sp->value.ia[i] = get_sint16(st, p);
713
26.3k
                          dsx:trace_scalar(pxs->memory, " %ld", long,
714
26.3k
                                         ia);
715
26.3k
                            --p;
716
26.3k
                            continue;
717
6
                        case pxt_sint32 & 7:
718
6
                            sp->type |= pxd_sint32;
719
19
                            for (i = 0; i < count; p += 4, ++i)
720
13
                                sp->value.ia[i] = get_sint32(st, p);
721
6
                            goto dsx;
722
1.06k
                        case pxt_real32 & 7:
723
1.06k
                            sp->type |= pxd_real32;
724
2.35k
                            for (i = 0; i < count; p += 4, ++i)
725
1.29k
                                sp->value.ra[i] = get_real32(st, p);
726
1.06k
                            trace_scalar(pxs->memory, " %g", double, ra);
727
728
1.06k
                            --p;
729
1.06k
                            continue;
730
6
                        default:
731
6
                            break;
732
99.6k
                    }
733
99.6k
                }
734
6
                break;
735
11.8k
            case 25:
736
                /* Array data */
737
11.8k
                {
738
11.8k
                    const byte *dp;
739
11.8k
                    uint nbytes;
740
741
11.8k
                    if (sp == stack_limit) {
742
0
                        code = gs_note_error(errorInternalOverflow);
743
0
                        goto x;
744
0
                    }
745
11.8k
                    switch (p[2]) {
746
1.93k
                        case pxt_ubyte:
747
1.93k
                            sp[1].value.array.size = p[3];
748
1.93k
                            dp = p + 4;
749
1.93k
                            break;
750
9.86k
                        case pxt_uint16:
751
9.86k
                            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
9.85k
                            sp[1].value.array.size = get_uint16(st, p + 3);
758
9.85k
                            dp = p + 5;
759
9.85k
                            break;
760
34
                        default:
761
34
                            st->last_operator = tag;    /* for error message */
762
34
                            code = gs_note_error(errorIllegalTag);
763
34
                            goto x;
764
11.8k
                    }
765
11.7k
                    nbytes = sp[1].value.array.size;
766
11.7k
                    if_debug1m('i', memory, "[%u]\n", sp[1].value.array.size);
767
11.7k
                    switch (tag) {
768
11.7k
                        case pxt_ubyte_array:
769
11.7k
                            sp[1].type = pxd_array | pxd_ubyte;
770
11.7k
                          array:++sp;
771
11.7k
                            if (st->big_endian)
772
0
                                sp->type |= pxd_big_endian;
773
11.7k
                            sp->value.array.data = dp;
774
11.7k
                            sp->attribute = 0;
775
                            /* Check whether we have enough data for the entire */
776
                            /* array. */
777
11.7k
                            if (rlimit + 1 - dp < nbytes) {     /* Exit now, continue reading when we return. */
778
214
                                uint avail = rlimit + 1 - dp;
779
780
214
                                code = px_save_array(sp, pxs, "partial array",
781
214
                                                     avail);
782
214
                                if (code < 0)
783
0
                                    goto x;
784
214
                                sp->type |= pxd_on_heap;
785
214
                                st->data_left = nbytes - avail;
786
214
                                st->data_proc = 0;
787
214
                                p = rlimit;
788
214
                                goto x;
789
214
                            }
790
11.5k
                            p = dp + nbytes - 1;
791
11.5k
                            trace_array(memory, sp);
792
11.5k
                            continue;
793
2
                        case pxt_uint16_array:
794
2
                            sp[1].type = pxd_array | pxd_uint16;
795
4
                          a16:nbytes <<= 1;
796
4
                            goto array;
797
0
                        case pxt_uint32_array:
798
0
                            sp[1].type = pxd_array | pxd_uint32;
799
2
                          a32:nbytes <<= 2;
800
2
                            goto array;
801
2
                        case pxt_sint16_array:
802
2
                            sp[1].type = pxd_array | pxd_sint16;
803
2
                            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
11.7k
                    }
813
2
                    break;
814
11.7k
                }
815
2
                break;
816
110k
            case 31:
817
110k
                {
818
110k
                    px_attribute_t attr;
819
110k
                    const byte *pnext;
820
821
110k
                    switch (tag) {
822
110k
                        case pxt_attr_ubyte:
823
110k
                            attr = p[2];
824
110k
                            pnext = p + 2;
825
110k
                            goto a;
826
1
                        case pxt_attr_uint16:
827
1
                            attr = get_uint16(st, p + 2);
828
1
                            pnext = p + 3;
829
110k
                          a:if (attr >=
830
110k
                                px_attribute_next)
831
94
                                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
110k
                            sp->attribute = attr;
843
110k
                            if (st->attribute_indices[attr] != 0) {
844
9
                                px_value_t *old_sp =
845
9
                                    &st->stack[st->attribute_indices[attr]];
846
                                /* If the old value is on the heap, free it. */
847
9
                                if (old_sp->type & pxd_on_heap)
848
0
                                    gs_free_object(memory,
849
9
                                                   (void *)old_sp->value.
850
9
                                                   array.data,
851
9
                                                   "old value for duplicate attribute");
852
9
                                *old_sp = *sp--;
853
9
                            } else
854
110k
                                st->attribute_indices[attr] = sp - st->stack;
855
110k
                            p = pnext;
856
110k
                            continue;
857
33
                        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
33
                            if (uint32at(p + 2, true /*arbitrary */ ) == 0) {
865
1
                                p += 5;
866
1
                                continue;
867
1
                            }
868
32
                            break;
869
32
                        case pxt_dataLengthByte:
870
                            /* See the comment under pxt_dataLength above. */
871
28
                            if (p[2] == 0) {
872
19
                                p += 2;
873
19
                                continue;
874
19
                            }
875
9
                            break;
876
193
                        default:
877
193
                            break;
878
110k
                    }
879
110k
                }
880
328
                break;
881
351
            default:
882
351
                break;
883
387k
        }
884
        /* Unknown tag value.  Report an error. */
885
1.47k
        st->last_operator = tag;        /* for error message */
886
1.47k
        code = gs_note_error(errorIllegalTag);
887
1.47k
        break;
888
387k
    }
889
6.14k
  x:                           /* Save any leftover input. */
890
6.14k
    left = rlimit - p;
891
6.14k
    if (rlimit != pr->limit) {  /* We were reading saved input. */
892
202
        if (left <= next_p - orig_p) {  /* We finished reading the previously saved input. */
893
            /* Continue reading current input, unless we got an error. */
894
200
            p = next_p -= left;
895
200
            rlimit = pr->limit;
896
200
            st->saved_count = 0;
897
200
            if (code >= 0)
898
135
                goto parse;
899
200
        } else {                /* There's still some previously saved input left over. */
900
2
            memmove(st->saved, p + 1, st->saved_count = left);
901
2
            p = next_p;
902
2
            rlimit = pr->limit;
903
2
            left = rlimit - p;
904
2
        }
905
202
    }
906
    /* Except in case of error, save any remaining input. */
907
6.01k
    if (code >= 0) {
908
834
        if (left + st->saved_count > sizeof(st->saved)) {       /* Fatal error -- shouldn't happen! */
909
10
            code = gs_note_error(errorInternalOverflow);
910
10
            st->saved_count = 0;
911
824
        } else {
912
824
            memcpy(&st->saved[st->saved_count], p + 1, left);
913
824
            st->saved_count += left;
914
824
            p = rlimit;
915
824
        }
916
834
    }
917
6.01k
    pr->ptr = p;
918
6.01k
    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
9.32k
    for (; sp > st->stack; --sp)
922
3.30k
        if ((sp->type & (pxd_array | pxd_on_heap)) == pxd_array) {
923
428
            int code = px_save_array(sp, pxs, "px stack array to heap",
924
428
                                     sp->value.array.size * value_size(sp));
925
926
428
            if (code < 0)
927
0
                break;
928
428
            sp->type |= pxd_on_heap;
929
428
        }
930
6.01k
    if (code < 0 && syntax != 0) {      /* Undo the state transition. */
931
5.18k
        st->macro_state ^= syntax->state_transition;
932
5.18k
    }
933
6.01k
    return code;
934
6.14k
}
935
936
uint
937
px_parser_data_left(px_parser_state_t * pxp)
938
8
{
939
8
    return pxp->data_left;
940
8
}