Coverage Report

Created: 2026-04-01 07:17

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