Coverage Report

Created: 2026-02-14 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/psi/iscanbin.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
/* Ghostscript binary token scanner and writer */
18
#include "math_.h"
19
#include "memory_.h"
20
#include "ghost.h"
21
#include "gsutil.h"
22
#include "gxalloc.h"    /* for names_array in allocator */
23
#include "stream.h"
24
#include "strimpl.h"    /* for sfilter.h */
25
#include "sfilter.h"    /* for iscan.h */
26
#include "ierrors.h"
27
#include "ialloc.h"
28
#include "iddict.h"
29
#include "dstack.h"   /* for immediately evaluated names */
30
#include "ostack.h"   /* must precede iscan.h */
31
#include "iname.h"
32
#include "iscan.h"    /* for scan_Refill */
33
#include "iscanbin.h"
34
#include "iutil.h"
35
#include "ivmspace.h"
36
#include "store.h"
37
#include "btoken.h"
38
#include "ibnum.h"
39
40
/* Define the binary token types. */
41
typedef enum {
42
    BT_SEQ = 128,   /* binary object sequence: */
43
    BT_SEQ_IEEE_MSB = 128,  /* IEEE floats, big-endian */
44
    BT_SEQ_IEEE_LSB = 129,  /* IEEE float, little-endian */
45
    BT_SEQ_NATIVE_MSB = 130,  /* native floats, big-endian */
46
    BT_SEQ_NATIVE_LSB = 131,  /* native floats, little-endian */
47
1.90M
#define BT_IS_SEQ(btype) (((btype) & ~3) == BT_SEQ)
48
    BT_INT32_MSB = 132,
49
    BT_INT32_LSB = 133,
50
    BT_INT16_MSB = 134,
51
    BT_INT16_LSB = 135,
52
    BT_INT8 = 136,
53
    BT_FIXED = 137,
54
    BT_FLOAT_IEEE_MSB = 138,
55
    BT_FLOAT_IEEE_LSB = 139,
56
    BT_FLOAT_NATIVE = 140,
57
    BT_BOOLEAN = 141,
58
    BT_STRING_256 = 142,
59
    BT_STRING_64K_MSB = 143,
60
    BT_STRING_64K_LSB = 144,
61
    BT_LITNAME_SYSTEM = 145,
62
    BT_EXECNAME_SYSTEM = 146,
63
    BT_LITNAME_USER = 147,
64
    BT_EXECNAME_USER = 148,
65
    BT_NUM_ARRAY = 149
66
} bin_token_type_t;
67
68
5.68M
#define MIN_BIN_TOKEN_TYPE 128
69
#define MAX_BIN_TOKEN_TYPE 159
70
#define NUM_BIN_TOKEN_TYPES (MAX_BIN_TOKEN_TYPE - MIN_BIN_TOKEN_TYPE + 1)
71
72
/* Define the number of required initial bytes for binary tokens. */
73
static const byte bin_token_bytes[NUM_BIN_TOKEN_TYPES] =
74
{
75
    4, 4, 4, 4, 5, 5, 3, 3, 2, 2, 5, 5, 5,
76
    2, 2, 3, 3, 2, 2, 2, 2, 4,
77
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1  /* undefined */
78
};
79
80
/* Define the number formats for those binary tokens that need them. */
81
static const byte bin_token_num_formats[NUM_BIN_TOKEN_TYPES] =
82
{
83
    num_msb + num_float_IEEE, /* BT_SEQ_IEEE_MSB */
84
    num_lsb + num_float_IEEE, /* BT_SEQ_IEEE_LSB */
85
#if ARCH_FLOATS_ARE_IEEE && BYTE_SWAP_IEEE_NATIVE_REALS
86
    /* Treat native floats like IEEE floats for byte swapping. */
87
    num_msb + num_float_IEEE, /* BT_SEQ_NATIVE_MSB */
88
    num_lsb + num_float_IEEE, /* BT_SEQ_NATIVE_LSB */
89
#else
90
    num_msb + num_float_native, /* BT_SEQ_NATIVE_MSB */
91
    num_lsb + num_float_native, /* BT_SEQ_NATIVE_LSB */
92
#endif
93
    num_msb + num_int32,  /* BT_INT32_MSB */
94
    num_lsb + num_int32,  /* BT_INT32_LSB */
95
    num_msb + num_int16,  /* BT_INT16_MSB */
96
    num_lsb + num_int16,  /* BT_INT16_LSB */
97
    0,        /* BT_INT8, not used */
98
    0,        /* BT_FIXED, not used */
99
    num_msb + num_float_IEEE, /* BT_FLOAT_IEEE_MSB */
100
    num_lsb + num_float_IEEE, /* BT_FLOAT_IEEE_LSB */
101
    num_float_native,   /* BT_FLOAT_NATIVE */
102
    0,        /* BT_BOOLEAN, not used */
103
    0,        /* BT_STRING_256, not used */
104
    num_msb,      /* BT_STRING_64K_MSB */
105
    num_lsb     /* BT_STRING_64K_LSB */
106
    /* rest not used */
107
};
108
109
/* Binary object sequence element types */
110
typedef enum {
111
    BS_TYPE_NULL = 0,
112
    BS_TYPE_INTEGER = 1,
113
    BS_TYPE_REAL = 2,
114
    BS_TYPE_NAME = 3,
115
    BS_TYPE_BOOLEAN = 4,
116
    BS_TYPE_STRING = 5,
117
    BS_TYPE_EVAL_NAME = 6,
118
    BS_TYPE_ARRAY = 9,
119
    BS_TYPE_MARK = 10,
120
} bin_seq_type_t;
121
122
2
#define BS_EXECUTABLE 128
123
57.7k
#define SIZEOF_BIN_SEQ_OBJ ((uint)8)
124
125
/* Forward references */
126
static int scan_bos(i_ctx_t *, ref *, scanner_state *);
127
static void scan_bos_error(scanner_state *, const char *);
128
static int scan_bin_scalar(i_ctx_t *, ref *, scanner_state *);
129
static int scan_bin_get_name(scanner_state *, const gs_memory_t *mem, const ref *, int, ref *, const char *);
130
static int scan_bin_num_array_continue(i_ctx_t *, ref *, scanner_state *);
131
static int scan_bin_string_continue(i_ctx_t *, ref *, scanner_state *);
132
static int scan_bos_continue(i_ctx_t *, ref *, scanner_state *);
133
static byte *scan_bos_resize(i_ctx_t *, scanner_state *, uint, uint);
134
static int scan_bos_string_continue(i_ctx_t *, ref *, scanner_state *);
135
136
/* Scan a binary token.  Called from the main scanner */
137
/* when it encounters an ASCII code 128-159, */
138
/* if binary tokens are being recognized (object format != 0). */
139
int
140
scan_binary_token(i_ctx_t *i_ctx_p, ref *pref, scanner_state *pstate)
141
1.90M
{
142
1.90M
    stream *const s = pstate->s_file.value.pfile;
143
1.90M
    scan_binary_state *const pbs = &pstate->s_ss.binary;
144
1.90M
    s_declare_inline(s, p, rlimit);
145
1.90M
    int btype, code;
146
1.90M
    uint wanted;
147
148
1.90M
    s_begin_inline(s, p, rlimit);
149
1.90M
    pbs->token_type = btype = *p;
150
1.90M
    wanted = bin_token_bytes[btype - MIN_BIN_TOKEN_TYPE] - 1;
151
1.90M
    if (rlimit - p < wanted) {
152
8.50k
        s_end_inline(s, p - 1, rlimit);
153
8.50k
        pstate->s_scan_type = scanning_none;
154
8.50k
        code = scan_Refill;
155
1.90M
    } else {
156
1.90M
        pbs->num_format = bin_token_num_formats[btype - MIN_BIN_TOKEN_TYPE];
157
1.90M
        if (BT_IS_SEQ(btype))
158
29.9k
            code = scan_bos(i_ctx_p, pref, pstate);
159
1.87M
        else
160
1.87M
            code = scan_bin_scalar(i_ctx_p, pref, pstate);
161
1.90M
    }
162
1.90M
    if (code == scan_Refill && s->end_status == EOFC)
163
6.16k
        code = gs_note_error(gs_error_syntaxerror);
164
1.90M
    if (code < 0 && pstate->s_error.string[0] == 0)
165
7.23k
        snprintf(pstate->s_error.string, sizeof(pstate->s_error.string),
166
7.23k
                 "binary token, type=%d", btype);
167
1.90M
    return code;
168
1.90M
}
169
170
/* Scan a binary object sequence. */
171
static int
172
scan_bos(i_ctx_t *i_ctx_p, ref *pref, scanner_state *pstate)
173
29.9k
{
174
29.9k
    stream *const s = pstate->s_file.value.pfile;
175
29.9k
    scan_binary_state *const pbs = &pstate->s_ss.binary;
176
29.9k
    s_declare_inline(s, p, rlimit);
177
29.9k
    int num_format = pbs->num_format;
178
29.9k
    int code;
179
180
29.9k
    s_begin_inline(s, p, rlimit);
181
29.9k
    {
182
29.9k
        uint rcnt = rlimit - p;
183
29.9k
        uint top_size = p[1];
184
29.9k
        uint hsize, size;
185
186
29.9k
        if (top_size == 0) {
187
            /* Extended header (2-byte array size, 4-byte length) */
188
189
28.4k
            if (rcnt < 7) {
190
363
                s_end_inline(s, p - 1, rlimit);
191
363
                pstate->s_scan_type = scanning_none;
192
363
                return scan_Refill;
193
363
            }
194
28.0k
            pbs->top_size = top_size = sdecodeushort(p + 2, num_format);
195
28.0k
            pbs->lsize = size = sdecodeint32(p + 4, num_format);
196
28.0k
            hsize = 8;
197
28.0k
        } else {
198
            /* Normal header (1-byte array size, 2-byte length). */
199
            /* We already checked rcnt >= 3. */
200
1.53k
            pbs->top_size = top_size;
201
1.53k
            pbs->lsize = size = sdecodeushort(p + 2, num_format);
202
1.53k
            hsize = 4;
203
1.53k
        }
204
29.5k
        if (size < hsize || (size - hsize) >> 3 < top_size) {
205
90
            scan_bos_error(pstate, "sequence too short");
206
90
            return_error(gs_error_syntaxerror); /* size too small */
207
90
        }
208
29.4k
        { /* Preliminary syntax check to avoid potentialy large
209
           * memory allocation on junk data. Bug 688833
210
           */
211
29.4k
          const unsigned char *q, *rend = p + hsize + top_size*8;
212
213
29.4k
          if (rend > rlimit)
214
1.90k
              rend = rlimit;
215
46.2k
          for (q = p + hsize + 1; q < rend; q += 8) {
216
17.1k
             int c = q[-1] & 0x7f;
217
17.1k
             if (c > 10) {
218
272
                scan_bos_error(pstate, "invalid object type");
219
272
                return_error(gs_error_syntaxerror);
220
272
             }
221
16.8k
             if (*q != 0) {
222
54
                scan_bos_error(pstate, "non-zero unused field");
223
54
                return_error(gs_error_syntaxerror);
224
54
             }
225
16.8k
          }
226
29.4k
        }
227
        /*
228
         * Preallocate an array large enough for the worst case,
229
         * namely, all objects and no strings.  Note that we must
230
         * divide size by 8, not sizeof(ref), since array elements
231
         * in binary tokens always occupy 8 bytes regardless of the
232
         * size of a ref.
233
         */
234
29.1k
        code = ialloc_ref_array(&pbs->bin_array,
235
29.1k
                                a_all + a_executable, size / 8,
236
29.1k
                                "binary object sequence(objects)");
237
29.1k
        if (code < 0)
238
319
            return code;
239
28.8k
        p += hsize - 1;
240
28.8k
        size -= hsize;
241
28.8k
        s_end_inline(s, p, rlimit);
242
28.8k
        pbs->max_array_index = pbs->top_size = top_size;
243
28.8k
        pbs->min_string_index = pbs->size = size;
244
28.8k
        pbs->index = 0;
245
28.8k
        pstate->s_da.is_dynamic = false;
246
28.8k
        pstate->s_da.base = pstate->s_da.next =
247
28.8k
            pstate->s_da.limit = pstate->s_da.buf;
248
28.8k
        code = scan_bos_continue(i_ctx_p, pref, pstate);
249
28.8k
        if ((code == scan_Refill || code < 0) && pbs->index < r_size(&pbs->bin_array)) {
250
            /* Clean up array for GC. */
251
1.25k
            uint index = pbs->index;
252
253
1.25k
            refset_null(pbs->bin_array.value.refs + index,
254
1.25k
                        r_size(&pbs->bin_array) - index);
255
1.25k
        }
256
28.8k
        return code;
257
29.1k
    }
258
29.1k
}
259
260
/* Report an error in a binary object sequence. */
261
static void
262
scan_bos_error(scanner_state *pstate, const char *msg)
263
844
{
264
844
    snprintf(pstate->s_error.string, sizeof(pstate->s_error.string),
265
844
             "bin obj seq, type=%d, elements=%u, size=%lu, %s",
266
844
             pstate->s_ss.binary.token_type,
267
844
             pstate->s_ss.binary.top_size,
268
844
             pstate->s_ss.binary.lsize, msg);
269
844
}
270
271
/* Scan a non-sequence binary token. */
272
static int
273
scan_bin_scalar(i_ctx_t *i_ctx_p, ref *pref, scanner_state *pstate)
274
1.87M
{
275
1.87M
    stream *const s = pstate->s_file.value.pfile;
276
1.87M
    scan_binary_state *const pbs = &pstate->s_ss.binary;
277
1.87M
    s_declare_inline(s, p, rlimit);
278
1.87M
    int num_format = pbs->num_format, code;
279
1.87M
    uint wanted, arg;
280
281
1.87M
    s_begin_inline(s, p, rlimit);
282
1.87M
    wanted = bin_token_bytes[*p - MIN_BIN_TOKEN_TYPE] - 1;
283
1.87M
    switch (*p) {
284
29.3k
        case BT_INT8:
285
29.3k
            make_int(pref, (p[1] ^ 128) - 128);
286
29.3k
            s_end_inline(s, p + 1, rlimit);
287
29.3k
            return 0;
288
251k
        case BT_FIXED:
289
251k
            num_format = p[1];
290
251k
            if (!num_is_valid(num_format))
291
45
                return_error(gs_error_syntaxerror);
292
250k
            wanted = 1 + encoded_number_bytes(num_format);
293
250k
            if (rlimit - p < wanted) {
294
1.58k
                s_end_inline(s, p - 1, rlimit);
295
1.58k
                pstate->s_scan_type = scanning_none;
296
1.58k
                return scan_Refill;
297
1.58k
            }
298
249k
            code = sdecode_number(p + 2, num_format, pref);
299
249k
            goto rnum;
300
85.6k
        case BT_INT32_MSB:
301
94.4k
        case BT_INT32_LSB:
302
103k
        case BT_INT16_MSB:
303
112k
        case BT_INT16_LSB:
304
740k
        case BT_FLOAT_IEEE_MSB:
305
752k
        case BT_FLOAT_IEEE_LSB:
306
764k
        case BT_FLOAT_NATIVE:
307
764k
            code = sdecode_number(p + 1, num_format, pref);
308
1.01M
          rnum:
309
1.01M
            switch (code) {
310
113k
                case t_integer:
311
1.01M
                case t_real:
312
1.01M
                    r_set_type(pref, code);
313
1.01M
                    break;
314
0
                case t_null:
315
0
                    return_error(gs_error_syntaxerror);
316
20
                default:
317
20
                    return code;
318
1.01M
            }
319
1.01M
            s_end_inline(s, p + wanted, rlimit);
320
1.01M
            return 0;
321
5.93k
        case BT_BOOLEAN:
322
5.93k
            arg = p[1];
323
5.93k
            if (arg & ~1)
324
100
                return_error(gs_error_syntaxerror);
325
5.83k
            make_bool(pref, arg);
326
5.83k
            s_end_inline(s, p + 1, rlimit);
327
5.83k
            return 0;
328
11.3k
        case BT_STRING_256:
329
11.3k
            arg = *++p;
330
11.3k
            goto str;
331
1.99k
        case BT_STRING_64K_MSB:
332
5.13k
        case BT_STRING_64K_LSB:
333
5.13k
            arg = sdecodeushort(p + 1, num_format);
334
5.13k
            p += 2;
335
16.5k
          str:
336
16.5k
            if (s->foreign && rlimit - p >= arg) {
337
                /*
338
                 * Reference the string directly in the buffer.  It is
339
                 * marked writable for consistency with the non-direct
340
                 * case, but since the "buffer" may be data compiled into
341
                 * the executable, it is probably actually read-only.
342
                 */
343
0
                s_end_inline(s, p, rlimit);
344
0
                make_const_string(pref, a_all | avm_foreign, arg, sbufptr(s));
345
0
                return sbufskip(s, arg);
346
16.5k
            } else {
347
16.5k
                byte *str = ialloc_string(arg, "string token");
348
349
16.5k
                if (str == 0)
350
0
                    return_error(gs_error_VMerror);
351
16.5k
                s_end_inline(s, p, rlimit);
352
16.5k
                pstate->s_da.base = pstate->s_da.next = str;
353
16.5k
                pstate->s_da.limit = str + arg;
354
16.5k
                code = scan_bin_string_continue(i_ctx_p, pref, pstate);
355
16.5k
                if (code == scan_Refill || code < 0) {
356
874
                    pstate->s_da.is_dynamic = true;
357
874
                    make_null(&pbs->bin_array);    /* clean up for GC */
358
874
                    pbs->cont = scan_bin_string_continue;
359
874
                }
360
16.5k
                return code;
361
16.5k
            }
362
430k
        case BT_LITNAME_SYSTEM:
363
430k
            code = scan_bin_get_name(pstate, imemory, system_names_p, p[1],
364
430k
                                     pref, "system");
365
430k
            goto lname;
366
355k
        case BT_EXECNAME_SYSTEM:
367
355k
            code = scan_bin_get_name(pstate, imemory, system_names_p, p[1],
368
355k
                                     pref, "system");
369
355k
            goto xname;
370
56
        case BT_LITNAME_USER:
371
56
            code = scan_bin_get_name(pstate, imemory, user_names_p, p[1],
372
56
                                     pref, "user");
373
430k
          lname:
374
430k
            if (code < 0)
375
73
                return code;
376
430k
            s_end_inline(s, p + 1, rlimit);
377
430k
            return 0;
378
39
        case BT_EXECNAME_USER:
379
39
            code = scan_bin_get_name(pstate, imemory, user_names_p, p[1],
380
39
                                     pref, "user");
381
355k
          xname:
382
355k
            if (code < 0)
383
134
                return code;
384
355k
            r_set_attrs(pref, a_executable);
385
355k
            s_end_inline(s, p + 1, rlimit);
386
355k
            return 0;
387
17.0k
        case BT_NUM_ARRAY:
388
17.0k
            num_format = p[1];
389
17.0k
            if (!num_is_valid(num_format))
390
25
                return_error(gs_error_syntaxerror);
391
17.0k
            arg = sdecodeushort(p + 2, num_format);
392
17.0k
            code = ialloc_ref_array(&pbs->bin_array, a_all, arg,
393
17.0k
                                    "number array token");
394
17.0k
            if (code < 0)
395
0
                return code;
396
17.0k
            pbs->num_format = num_format;
397
17.0k
            pbs->index = 0;
398
17.0k
            p += 3;
399
17.0k
            s_end_inline(s, p, rlimit);
400
17.0k
            code = scan_bin_num_array_continue(i_ctx_p, pref, pstate);
401
17.0k
            if (code == scan_Refill || code < 0) {
402
                /* Make sure the array is clean for the GC. */
403
1.38k
                refset_null(pbs->bin_array.value.refs + pbs->index,
404
1.38k
                            arg - pbs->index);
405
1.38k
                pbs->cont = scan_bin_num_array_continue;
406
1.38k
            }
407
17.0k
            return code;
408
1.87M
    }
409
1.87M
    return_error(gs_error_syntaxerror);
410
1.87M
}
411
412
/* Get a system or user name. */
413
static int
414
scan_bin_get_name(scanner_state *pstate, const gs_memory_t *mem,
415
                  const ref *pnames /*t_array*/, int index, ref *pref,
416
                  const char *usstring)
417
786k
{
418
    /* Convert all errors to gs_error_undefined to match Adobe. */
419
786k
    if (pnames == 0 || array_get(mem, pnames, (long)index, pref) < 0 ||
420
786k
        !r_has_type(pref, t_name)) {
421
231
        snprintf(pstate->s_error.string,
422
231
                 sizeof(pstate->s_error.string),
423
231
                 "%s%d", usstring, index);
424
231
        pstate->s_error.is_name = true;
425
231
        return_error(gs_error_undefined);
426
231
    }
427
786k
    return 0;
428
786k
}
429
430
/* Continue collecting a binary string. */
431
static int
432
scan_bin_string_continue(i_ctx_t *i_ctx_p, ref * pref, scanner_state * pstate)
433
63.8k
{
434
63.8k
    stream *const s = pstate->s_file.value.pfile;
435
63.8k
    byte *q = pstate->s_da.next;
436
63.8k
    uint wanted = pstate->s_da.limit - q;
437
63.8k
    uint rcnt;
438
439
    /* We don't check the return status from 'sgets' here.
440
       If there is an error in sgets, the condition rcnt==wanted
441
       would be false and this function will return scan_Refill.
442
    */
443
63.8k
    sgets(s, q, wanted, &rcnt);
444
63.8k
    if (rcnt == wanted) {
445
        /* Finished collecting the string. */
446
43.2k
        make_string(pref, a_all | icurrent_space,
447
43.2k
                    pstate->s_da.limit - pstate->s_da.base,
448
43.2k
                    pstate->s_da.base);
449
43.2k
        return 0;
450
43.2k
    }
451
20.5k
    pstate->s_da.next = q + rcnt;
452
20.5k
    pstate->s_scan_type = scanning_binary;
453
20.5k
    return scan_Refill;
454
63.8k
}
455
456
/* Continue scanning a binary number array. */
457
static int
458
scan_bin_num_array_continue(i_ctx_t *i_ctx_p, ref * pref,
459
                            scanner_state * pstate)
460
24.2k
{
461
24.2k
    stream *const s = pstate->s_file.value.pfile;
462
24.2k
    scan_binary_state *const pbs = &pstate->s_ss.binary;
463
24.2k
    uint index = pbs->index;
464
24.2k
    ref *np = pbs->bin_array.value.refs + index;
465
24.2k
    uint wanted = encoded_number_bytes(pbs->num_format);
466
467
1.85M
    for (; index < r_size(&pbs->bin_array); index++, np++) {
468
1.84M
        int code;
469
470
1.84M
        if (sbufavailable(s) < wanted) {
471
8.41k
            pbs->index = index;
472
8.41k
            pstate->s_scan_type = scanning_binary;
473
8.41k
            return scan_Refill;
474
8.41k
        }
475
1.83M
        code = sdecode_number(sbufptr(s), pbs->num_format, np);
476
1.83M
        switch (code) {
477
114k
            case t_integer:
478
1.83M
            case t_real:
479
1.83M
                r_set_type(np, code);
480
1.83M
                (void)sbufskip(s, wanted);
481
1.83M
                break;
482
0
            case t_null:
483
0
                scan_bos_error(pstate, "bad number format");
484
0
                return_error(gs_error_syntaxerror);
485
23
            default:
486
23
                return code;
487
1.83M
        }
488
1.83M
    }
489
15.8k
    *pref = pbs->bin_array;
490
15.8k
    return 0;
491
24.2k
}
492
493
/*
494
 * Continue scanning a binary object sequence.  We preallocated space for
495
 * the largest possible number of objects, but not for strings, since
496
 * the latter would probably be a gross over-estimate.  Instead,
497
 * we wait until we see the first string or name, and allocate string space
498
 * based on the hope that its string index is the smallest one we will see.
499
 * If this turns out to be wrong, we may have to reallocate, and adjust
500
 * all the pointers.
501
 */
502
static int
503
scan_bos_continue(i_ctx_t *i_ctx_p, ref * pref, scanner_state * pstate)
504
29.0k
{
505
29.0k
    stream *const s = pstate->s_file.value.pfile;
506
29.0k
    scan_binary_state *const pbs = &pstate->s_ss.binary;
507
29.0k
    s_declare_inline(s, p, rlimit);
508
29.0k
    uint max_array_index = pbs->max_array_index;
509
29.0k
    uint min_string_index = pbs->min_string_index;
510
29.0k
    int num_format = pbs->num_format;
511
29.0k
    uint index = pbs->index;
512
29.0k
    uint size = pbs->size;
513
29.0k
    ref *abase = pbs->bin_array.value.refs;
514
29.0k
    int code;
515
516
29.0k
    pbs->cont = scan_bos_continue;  /* in case of premature return */
517
29.0k
    s_begin_inline(s, p, rlimit);
518
56.8k
    for (; index < max_array_index; p += SIZEOF_BIN_SEQ_OBJ, index++) {
519
29.2k
        ref *op = abase + index;
520
29.2k
        uint osize;
521
29.2k
        int value, atype, attrs;
522
523
29.2k
        s_end_inline(s, p, rlimit); /* in case of error */
524
29.2k
        if (rlimit - p < SIZEOF_BIN_SEQ_OBJ) {
525
979
            pbs->index = index;
526
979
            pbs->max_array_index = max_array_index;
527
979
            pbs->min_string_index = min_string_index;
528
979
            pstate->s_scan_type = scanning_binary;
529
979
            return scan_Refill;
530
979
        }
531
28.2k
        if (p[2] != 0) { /* reserved, must be 0 */
532
10
            scan_bos_error(pstate, "non-zero unused field");
533
10
            return_error(gs_error_syntaxerror);
534
10
        }
535
28.2k
        attrs = (p[1] & 128 ? a_executable : 0);
536
        /*
537
         * We always decode all 8 bytes of the object, so we can signal
538
         * syntaxerror if any unused field is non-zero (per PLRM).
539
         */
540
28.2k
        osize = sdecodeushort(p + 3, num_format);
541
28.2k
        value = sdecodeint32(p + 5, num_format);
542
28.2k
        switch (p[1] & 0x7f) {
543
25.9k
            case BS_TYPE_NULL:
544
25.9k
                if (osize | value) { /* unused */
545
157
                    scan_bos_error(pstate, "non-zero unused field");
546
157
                    return_error(gs_error_syntaxerror);
547
157
                }
548
25.7k
                make_null(op);
549
25.7k
                break;
550
71
            case BS_TYPE_INTEGER:
551
71
                if (osize) { /* unused */
552
16
                    scan_bos_error(pstate, "non-zero unused field");
553
16
                    return_error(gs_error_syntaxerror);
554
16
                }
555
55
                make_int(op, value);
556
55
                break;
557
1.80k
            case BS_TYPE_REAL:{
558
1.80k
                    float vreal;
559
560
1.80k
                    if (osize != 0) { /* fixed-point number */
561
42
                        if (osize > 31) {
562
16
                            scan_bos_error(pstate, "invalid number format");
563
16
                            return_error(gs_error_syntaxerror);
564
16
                        }
565
                        /* ldexp requires a signed 2nd argument.... */
566
26
                        vreal = (float)ldexp((double)value, -(int)osize);
567
1.76k
                    } else {
568
1.76k
                        code = sdecode_float(p + 5, num_format, &vreal);
569
1.76k
                        if (code < 0) {
570
6
                            scan_bos_error(pstate, "invalid real number");
571
6
                            return code;
572
6
                        }
573
1.76k
                    }
574
1.78k
                    make_real(op, vreal);
575
1.78k
                    break;
576
1.80k
                }
577
68
            case BS_TYPE_BOOLEAN:
578
68
                if (osize) { /* unused */
579
13
                    scan_bos_error(pstate, "non-zero unused field");
580
13
                    return_error(gs_error_syntaxerror);
581
13
                }
582
55
                make_bool(op, value != 0);
583
55
                break;
584
113
            case BS_TYPE_STRING:
585
113
                attrs |= a_all;
586
229
              str:
587
229
                if (osize == 0) {
588
                    /* For zero-length strings, the offset */
589
                    /* doesn't matter, and may be zero. */
590
56
                    make_empty_string(op, attrs);
591
56
                    break;
592
56
                }
593
173
                {
594
173
                    const uint beg_ofs = (uint)value;
595
173
                    const uint end_ofs = beg_ofs + osize;
596
597
173
                    if (beg_ofs < max_array_index * SIZEOF_BIN_SEQ_OBJ || beg_ofs > size) {
598
134
                        scan_bos_error(pstate, "invalid string offset");
599
134
                        return_error(gs_error_syntaxerror);
600
134
                    }
601
39
                    if (end_ofs < beg_ofs || end_ofs > size) {
602
9
                        scan_bos_error(pstate, "invalid string length");
603
9
                        return_error(gs_error_syntaxerror);
604
9
                    }
605
30
                    if (beg_ofs < min_string_index) {
606
                        /* We have to (re)allocate the strings. */
607
30
                        uint str_size = size - beg_ofs;
608
30
                        byte *sbase;
609
610
30
                        if (pstate->s_da.is_dynamic)
611
0
                            sbase = scan_bos_resize(i_ctx_p, pstate, str_size,
612
0
                                                    index);
613
30
                        else
614
30
                            sbase = ialloc_string(str_size,
615
30
                                                  "bos strings");
616
30
                        if (sbase == 0)
617
0
                            return_error(gs_error_VMerror);
618
30
                        pstate->s_da.is_dynamic = true;
619
30
                        pstate->s_da.base = pstate->s_da.next = sbase;
620
30
                        pstate->s_da.limit = sbase + str_size;
621
30
                        min_string_index = beg_ofs;
622
30
                    }
623
30
                    make_string(op, attrs | icurrent_space, osize,
624
30
                                pstate->s_da.base +
625
30
                                (beg_ofs - min_string_index));
626
30
                }
627
0
                break;
628
52
            case BS_TYPE_EVAL_NAME:
629
52
                attrs |= a_readonly; /* mark as executable for later */
630
                /* falls through */
631
144
            case BS_TYPE_NAME:
632
144
                switch (osize) {
633
12
                    case 0:
634
12
                        code = scan_bin_get_name(pstate, imemory,
635
12
                                                 user_names_p, value, op,
636
12
                                                 "user");
637
12
                        goto usn;
638
16
                    case 0xffff:
639
16
                        code = scan_bin_get_name(pstate, imemory,
640
16
                                                 system_names_p, value, op,
641
16
                                                 "system");
642
28
                      usn:
643
28
                        if (code < 0)
644
24
                            return code;
645
4
                        r_set_attrs(op, attrs);
646
4
                        break;
647
116
                    default:
648
116
                        goto str;
649
144
                }
650
4
                break;
651
72
            case BS_TYPE_ARRAY:
652
72
                atype = t_array;
653
72
                {
654
72
                    const uint beg_ofs = (uint)value;
655
72
                    const uint end_ofs = beg_ofs + osize * SIZEOF_BIN_SEQ_OBJ;
656
72
                    const uint beg_idx = beg_ofs / SIZEOF_BIN_SEQ_OBJ;
657
72
                    const uint end_idx = end_ofs / SIZEOF_BIN_SEQ_OBJ;
658
659
72
                    if (beg_ofs > min_string_index || beg_ofs & (SIZEOF_BIN_SEQ_OBJ - 1)) {
660
22
                        scan_bos_error(pstate, "bad array offset");
661
22
                        return_error(gs_error_syntaxerror);
662
22
                    }
663
50
                    if (osize > (size / 8) || end_ofs < beg_ofs || end_ofs > min_string_index) {
664
10
                        scan_bos_error(pstate, "bad array length");
665
10
                        return_error(gs_error_syntaxerror);
666
10
                    }
667
668
40
                    max_array_index = max(max_array_index, end_idx);
669
40
                    make_tasv_new(op, atype,
670
40
                                  attrs | a_all | icurrent_space,
671
40
                                  osize, refs, abase + beg_idx);
672
40
                }
673
0
                break;
674
41
            case BS_TYPE_MARK:
675
41
                if (osize | value) { /* unused */
676
20
                    scan_bos_error(pstate, "non-zero unused field");
677
20
                    return_error(gs_error_syntaxerror);
678
20
                }
679
21
                make_mark(op);
680
21
                break;
681
15
            default:
682
15
                scan_bos_error(pstate, "invalid object type");
683
15
                return_error(gs_error_syntaxerror);
684
28.2k
        }
685
28.2k
    }
686
27.6k
    s_end_inline(s, p, rlimit);
687
    /* Shorten the objects to remove the space that turned out */
688
    /* to be used for strings. */
689
27.6k
    pbs->index = max_array_index;
690
27.6k
    iresize_ref_array(&pbs->bin_array, max_array_index,
691
27.6k
                      "binary object sequence(objects)");
692
27.6k
    code = scan_bos_string_continue(i_ctx_p, pref, pstate);
693
27.6k
    if (code == scan_Refill)
694
7
        pbs->cont = scan_bos_string_continue;
695
27.6k
    return code;
696
29.0k
}
697
698
/* Reallocate the strings for a binary object sequence, */
699
/* adjusting all the pointers to them from objects. */
700
static byte *
701
scan_bos_resize(i_ctx_t *i_ctx_p, scanner_state * pstate, uint new_size,
702
                uint index)
703
0
{
704
0
    scan_binary_state *const pbs = &pstate->s_ss.binary;
705
0
    uint old_size = da_size(&pstate->s_da);
706
0
    byte *old_base = pstate->s_da.base;
707
0
    byte *new_base = iresize_string(old_base, old_size, new_size,
708
0
                                    "scan_bos_resize");
709
0
    byte *relocated_base = new_base + (new_size - old_size);
710
0
    uint i;
711
0
    ref *aptr = pbs->bin_array.value.refs;
712
713
0
    if (new_base == 0)
714
0
        return 0;
715
    /* Since the allocator normally extends strings downward, */
716
    /* it's quite possible that new and old addresses are the same. */
717
0
    if (relocated_base != old_base)
718
0
        for (i = index; i != 0; i--, aptr++)
719
0
            if (r_has_type(aptr, t_string) && r_size(aptr) != 0)
720
0
                aptr->value.bytes =
721
0
                    aptr->value.bytes - old_base + relocated_base;
722
0
    return new_base;
723
0
}
724
725
/* Continue reading the strings for a binary object sequence. */
726
static int
727
scan_bos_string_continue(i_ctx_t *i_ctx_p, ref * pref,
728
                         scanner_state * pstate)
729
27.6k
{
730
27.6k
    scan_binary_state *const pbs = &pstate->s_ss.binary;
731
27.6k
    ref rstr;
732
27.6k
    ref *op;
733
27.6k
    int code = scan_bin_string_continue(i_ctx_p, &rstr, pstate);
734
27.6k
    uint space = ialloc_space(idmemory);
735
27.6k
    uint i;
736
737
27.6k
    if (code != 0)
738
7
        return code;
739
740
    /* Fix up names.  We must do this before creating dictionaries. */
741
742
27.6k
    for (op = pbs->bin_array.value.refs, i = r_size(&pbs->bin_array);
743
36.0k
         i != 0; i--, op++
744
27.6k
         )
745
8.38k
        switch (r_type(op)) {
746
22
            case t_string:
747
22
                if (r_has_attr(op, a_write))  /* a real string */
748
22
                    break;
749
                /* This is actually a name; look it up now. */
750
0
                {
751
0
                    uint attrs = r_type_attrs(op) & (a_read | a_executable);
752
753
0
                    code = name_ref(imemory, op->value.bytes, r_size(op), op, 1);
754
0
                    if (code < 0)
755
0
                        return code;
756
0
                    r_set_attrs(op, attrs);
757
0
                }
758
                /* falls through */
759
0
            case t_name:
760
0
                if (r_has_attr(op, a_read)) { /* BS_TYPE_EVAL_NAME */
761
0
                    ref *defp = dict_find_name(op);
762
763
0
                    if (defp == 0)
764
0
                        return_error(gs_error_undefined);
765
0
                    store_check_space(space, defp);
766
0
                    ref_assign(op, defp);
767
0
                }
768
0
                break;
769
8.38k
        }
770
771
27.6k
    ref_assign(pref, &pbs->bin_array);
772
27.6k
    r_set_size(pref, pbs->top_size);
773
27.6k
    return scan_BOS;
774
27.6k
}
775
776
/* ---------------- Writing ---------------- */
777
778
/*
779
 * Encode a single object for a binary object sequence, for printobject and
780
 * write object.  Note that this does not modify the always-unused byte (1),
781
 * but it always write bytes 0 and 2-7.
782
 */
783
int
784
encode_binary_token(i_ctx_t *i_ctx_p, const ref *obj, ps_int *ref_offset,
785
                    ps_int *char_offset, byte *str)
786
63
{
787
63
    bin_seq_type_t type;
788
63
    uint size = 0;
789
63
    int format = (int)ref_binary_object_format.value.intval;
790
63
    ps_int value = 0;
791
63
    ref nstr;
792
793
63
    switch (r_type(obj)) {
794
0
        case t_null:
795
0
            type = BS_TYPE_NULL;
796
0
            break;   /* always set all fields */
797
22
        case t_mark:
798
22
            type = BS_TYPE_MARK;
799
22
            break;   /* always set all fields */
800
15
        case t_integer:
801
15
            type = BS_TYPE_INTEGER;
802
15
            value = obj->value.intval;
803
15
            break;
804
7
        case t_real:
805
7
            type = BS_TYPE_REAL;
806
7
            if (sizeof(obj->value.realval) != sizeof(int)) {
807
                /* The PLRM allocates exactly 4 bytes for reals. */
808
0
                return_error(gs_error_rangecheck);
809
0
            }
810
7
            value = *(const ps_int *)&obj->value.realval;
811
#if !(ARCH_FLOATS_ARE_IEEE && BYTE_SWAP_IEEE_NATIVE_REALS)
812
            if (format >= 3) {
813
                /* Never byte-swap native reals -- use native byte order. */
814
                format = 4 - ARCH_IS_BIG_ENDIAN;
815
            }
816
#endif
817
7
            break;
818
0
        case t_boolean:
819
0
            type = BS_TYPE_BOOLEAN;
820
0
            value = obj->value.boolval;
821
0
            break;
822
4
        case t_array:
823
4
            type = BS_TYPE_ARRAY;
824
4
            size = r_size(obj);
825
4
           value = *ref_offset;
826
4
            *ref_offset += size * SIZEOF_BIN_SEQ_OBJ;
827
4
            break;
828
5
        case t_string:
829
5
            type = BS_TYPE_STRING;
830
15
nos:
831
15
            size = r_size(obj);
832
15
            value = *char_offset;
833
15
            *char_offset += size;
834
15
            break;
835
10
        case t_name:
836
10
            type = BS_TYPE_NAME;
837
10
            name_string_ref(imemory, obj, &nstr);
838
10
            r_copy_attrs(&nstr, a_executable, obj);
839
10
            obj = &nstr;
840
10
            goto nos;
841
0
        default:
842
0
            return_error(gs_error_rangecheck);
843
63
    }
844
63
    {
845
63
        byte s0 = (byte) size, s1 = (byte) (size >> 8);
846
63
        byte v0 = (byte) value, v1 = (byte) (value >> 8),
847
63
            v2 = (byte) (value >> 16), v3 = (byte) (value >> 24);
848
849
63
        if (format & 1) {
850
            /* Store big-endian */
851
0
            str[2] = s1, str[3] = s0;
852
0
            str[4] = v3, str[5] = v2, str[6] = v1, str[7] = v0;
853
63
        } else {
854
            /* Store little-endian */
855
63
            str[2] = s0, str[3] = s1;
856
63
            str[4] = v0, str[5] = v1, str[6] = v2, str[7] = v3;
857
63
        }
858
63
    }
859
63
    if (r_has_attr(obj, a_executable))
860
2
        type += BS_EXECUTABLE;
861
63
    str[0] = (byte) type;
862
63
    return 0;
863
63
}