Coverage Report

Created: 2025-06-10 06:58

/src/ghostpdl/psi/iutil.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2024 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
/* Utilities for Ghostscript interpreter */
18
#include "math_.h"    /* for fabs */
19
#include "memory_.h"
20
#include "string_.h"
21
#include "ghost.h"
22
#include "ierrors.h"
23
#include "gsccode.h"    /* for gxfont.h */
24
#include "gsmatrix.h"
25
#include "gsutil.h"
26
#include "gxfont.h"
27
#include "strimpl.h"
28
#include "sstring.h"
29
#include "idict.h"
30
#include "ifont.h"    /* for FontID equality */
31
#include "imemory.h"
32
#include "iname.h"
33
#include "ipacked.h"    /* for array_get */
34
#include "iutil.h"    /* for checking prototypes */
35
#include "ivmspace.h"
36
#include "oper.h"
37
#include "store.h"
38
39
/*
40
 * By design choice, none of the procedures in this file take a context
41
 * pointer (i_ctx_p).  Since a number of them require a gs_dual_memory_t
42
 * for store checking or save bookkeeping, we need to #undef idmemory.
43
 */
44
#undef idmemory
45
46
/* ------ Object utilities ------ */
47
48
/* Define the table of ref type properties. */
49
const byte ref_type_properties[] = {
50
    REF_TYPE_PROPERTIES_DATA
51
};
52
53
/* Copy refs from one place to another. */
54
int
55
refcpy_to_old(ref * aref, uint index, const ref * from,
56
              uint size, gs_dual_memory_t *idmemory, client_name_t cname)
57
39.3M
{
58
39.3M
    ref *to = aref->value.refs + index;
59
39.3M
    int code = refs_check_space(from, size, r_space(aref));
60
61
39.3M
    if (code < 0)
62
0
        return code;
63
    /* We have to worry about aliasing.... */
64
39.3M
    if (to <= from || from + size <= to)
65
109M
        while (size--)
66
69.7M
            ref_assign_old(aref, to, from, cname), to++, from++;
67
0
    else
68
0
        for (from += size, to += size; size--;)
69
0
            from--, to--, ref_assign_old(aref, to, from, cname);
70
39.3M
    return 0;
71
39.3M
}
72
void
73
refcpy_to_new(ref * to, const ref * from, uint size,
74
              gs_dual_memory_t *idmemory)
75
0
{
76
0
    while (size--)
77
0
        ref_assign_new(to, from), to++, from++;
78
0
}
79
80
/* Fill a new object with nulls. */
81
void
82
refset_null_new(ref * to, uint size, uint new_mask)
83
53.0M
{
84
1.31G
    for (; size--; ++to)
85
1.25G
        make_ta(to, t_null, new_mask);
86
53.0M
}
87
88
/* Compare two objects for equality. */
89
static bool fid_eq(const gs_memory_t *mem, const gs_font *pfont1,
90
                    const gs_font *pfont2);
91
bool
92
obj_eq(const gs_memory_t *mem, const ref * pref1, const ref * pref2)
93
301M
{
94
301M
    ref nref;
95
96
301M
    if (r_type(pref1) != r_type(pref2)) {
97
        /*
98
         * Only a few cases need be considered here:
99
         * integer/real (and vice versa), name/string (and vice versa),
100
         * arrays, and extended operators.
101
         */
102
51.5M
        switch (r_type(pref1)) {
103
27.2k
            case t_integer:
104
27.2k
                return (r_has_type(pref2, t_real) &&
105
27.2k
                        pref2->value.realval == pref1->value.intval);
106
1.64k
            case t_real:
107
1.64k
                return (r_has_type(pref2, t_integer) &&
108
1.64k
                        pref2->value.intval == pref1->value.realval);
109
44.0M
            case t_name:
110
44.0M
                if (!r_has_type(pref2, t_string))
111
43.1M
                    return false;
112
879k
                name_string_ref(mem, pref1, &nref);
113
879k
                pref1 = &nref;
114
879k
                break;
115
1.02M
            case t_string:
116
1.02M
                if (!r_has_type(pref2, t_name))
117
124k
                    return false;
118
896k
                name_string_ref(mem, pref2, &nref);
119
896k
                pref2 = &nref;
120
896k
                break;
121
                /*
122
                 * Differing implementations of packedarray can be eq,
123
                 * if the length is zero, but an array is never eq to a
124
                 * packedarray.
125
                 */
126
45.0k
            case t_mixedarray:
127
45.0k
            case t_shortarray:
128
                /*
129
                 * Since r_type(pref1) is one of the above, this is a
130
                 * clever fast check for r_type(pref2) being the other.
131
                 */
132
45.0k
                return ((int)r_type(pref1) + (int)r_type(pref2) ==
133
45.0k
                        t_mixedarray + t_shortarray) &&
134
45.0k
                    r_size(pref1) == 0 && r_size(pref2) == 0;
135
6.35M
            default:
136
6.35M
                if (r_btype(pref1) != r_btype(pref2))
137
6.35M
                    return false;
138
51.5M
        }
139
51.5M
    }
140
    /*
141
     * Now do a type-dependent comparison.  This would be very simple if we
142
     * always filled in all the bytes of a ref, but we currently don't.
143
     */
144
252M
    switch (r_btype(pref1)) {
145
91.6k
        case t_array:
146
91.6k
            return ((pref1->value.refs == pref2->value.refs ||
147
91.6k
                     r_size(pref1) == 0) &&
148
91.6k
                    r_size(pref1) == r_size(pref2));
149
0
        case t_mixedarray:
150
8.88k
        case t_shortarray:
151
8.88k
            return ((pref1->value.packed == pref2->value.packed ||
152
8.88k
                     r_size(pref1) == 0) &&
153
8.88k
                    r_size(pref1) == r_size(pref2));
154
53.3k
        case t_boolean:
155
53.3k
            return (pref1->value.boolval == pref2->value.boolval);
156
684k
        case t_dictionary:
157
684k
            return (pref1->value.pdict == pref2->value.pdict);
158
7.99k
        case t_file:
159
7.99k
            return (pref1->value.pfile == pref2->value.pfile &&
160
7.99k
                    r_size(pref1) == r_size(pref2));
161
111M
        case t_integer:
162
111M
            return (pref1->value.intval == pref2->value.intval);
163
17.6k
        case t_mark:
164
6.61M
        case t_null:
165
6.61M
            return true;
166
126M
        case t_name:
167
126M
            return (pref1->value.pname == pref2->value.pname);
168
0
        case t_oparray:
169
0
        case t_operator:
170
0
            return (op_index(pref1) == op_index(pref2));
171
228
        case t_real:
172
228
            return (pref1->value.realval == pref2->value.realval);
173
3
        case t_save:
174
3
            return (pref2->value.saveid == pref1->value.saveid);
175
7.10M
        case t_string:
176
7.10M
            return (!bytes_compare(pref1->value.bytes, r_size(pref1),
177
7.10M
                                   pref2->value.bytes, r_size(pref2)));
178
0
        case t_device:
179
0
            return (pref1->value.pdevice->device == pref2->value.pdevice->device);
180
0
        case t_struct:
181
0
        case t_astruct:
182
0
        case t_pdfctx:
183
0
            return (pref1->value.pstruct == pref2->value.pstruct);
184
0
        case t_fontID:
185
            /* This is complicated enough to deserve a separate procedure. */
186
0
            return fid_eq(mem, r_ptr(pref1, gs_font), r_ptr(pref2, gs_font));
187
252M
    }
188
0
    return false;   /* shouldn't happen! */
189
252M
}
190
191
/*
192
 * Compare two FontIDs for equality.  In the Adobe implementations,
193
 * different scalings of a font have "equal" FIDs, so we do the same.
194
 * Furthermore, in more recent Adobe interpreters, different *copies* of a
195
 * font have equal FIDs -- at least for Type 1 and Type 3 fonts -- as long
196
 * as the "contents" of the font are the same.  We aren't sure that the
197
 * following matches the Adobe algorithm, but it's close enough to pass the
198
 * Genoa CET.
199
 */
200
/* (This is a single-use procedure, for clearer code.) */
201
static bool
202
fid_eq(const gs_memory_t *mem, const gs_font *pfont1, const gs_font *pfont2)
203
0
{
204
0
    while (pfont1->base != pfont1)
205
0
        pfont1 = pfont1->base;
206
0
    while (pfont2->base != pfont2)
207
0
        pfont2 = pfont2->base;
208
0
    if (pfont1 == pfont2)
209
0
        return true;
210
0
    switch (pfont1->FontType) {
211
0
    case 1: case 3:
212
0
        if (pfont1->FontType == pfont2->FontType)
213
0
            break;
214
0
    default:
215
0
        return false;
216
0
    }
217
    /* The following, while peculiar, appears to match CPSI. */
218
0
    {
219
0
        const gs_uid *puid1 = &((const gs_font_base *)pfont1)->UID;
220
0
        const gs_uid *puid2 = &((const gs_font_base *)pfont2)->UID;
221
0
    if (uid_is_UniqueID(puid1) || uid_is_UniqueID(puid2) ||
222
0
        ((uid_is_XUID(puid1) || uid_is_XUID(puid2)) &&
223
0
         !uid_equal(puid1, puid2)))
224
0
        return false;
225
0
    }
226
0
    {
227
0
        const font_data *pfd1 = (const font_data *)pfont1->client_data;
228
0
        const font_data *pfd2 = (const font_data *)pfont2->client_data;
229
230
0
        if (!(obj_eq(mem, &pfd1->BuildChar, &pfd2->BuildChar) &&
231
0
              obj_eq(mem, &pfd1->BuildGlyph, &pfd2->BuildGlyph) &&
232
0
              obj_eq(mem, &pfd1->Encoding, &pfd2->Encoding) &&
233
0
              obj_eq(mem, &pfd1->CharStrings, &pfd2->CharStrings)))
234
0
            return false;
235
0
        if (pfont1->FontType == 1) {
236
0
            ref *ppd1, *ppd2;
237
238
0
            if (dict_find_string(&pfd1->dict, "Private", &ppd1) > 0 &&
239
0
                dict_find_string(&pfd2->dict, "Private", &ppd2) > 0 &&
240
0
                !obj_eq(mem, ppd1, ppd2))
241
0
                return false;
242
0
        }
243
0
    }
244
0
    return true;
245
0
}
246
247
/* Compare two objects for identity. */
248
bool
249
obj_ident_eq(const gs_memory_t *mem, const ref * pref1, const ref * pref2)
250
0
{
251
0
    if (r_type(pref1) != r_type(pref2))
252
0
        return false;
253
0
    if (r_has_type(pref1, t_string))
254
0
        return (pref1->value.bytes == pref2->value.bytes &&
255
0
                r_size(pref1) == r_size(pref2));
256
0
    return obj_eq(mem, pref1, pref2);
257
0
}
258
259
/*
260
 * Set *pchars and *plen to point to the data of a name or string, and
261
 * return 0.  If the object isn't a name or string, return gs_error_typecheck.
262
 * If the object is a string without read access, return gs_error_invalidaccess.
263
 */
264
int
265
obj_string_data(const gs_memory_t *mem, const ref *op, const byte **pchars, uint *plen)
266
17.9M
{
267
17.9M
    switch (r_type(op)) {
268
12.0M
    case t_name: {
269
12.0M
        ref nref;
270
271
12.0M
        name_string_ref(mem, op, &nref);
272
12.0M
        *pchars = nref.value.bytes;
273
12.0M
        *plen = r_size(&nref);
274
12.0M
        return 0;
275
0
    }
276
5.94M
    case t_string:
277
5.94M
        check_read(*op);
278
5.94M
        *pchars = op->value.bytes;
279
5.94M
        *plen = r_size(op);
280
5.94M
        return 0;
281
0
    default:
282
0
        return_error(gs_error_typecheck);
283
17.9M
    }
284
17.9M
}
285
286
/*
287
 * Create a printable representation of an object, a la cvs and =
288
 * (full_print = 0), == (full_print = 1), or === (full_print = 2).  Return 0
289
 * if OK, 1 if the destination wasn't large enough, gs_error_invalidaccess if the
290
 * object's contents weren't readable.  If the return value is 0 or 1,
291
 * *prlen contains the amount of data returned.  start_pos is the starting
292
 * output position -- the first start_pos bytes of output are discarded.
293
 *
294
 * When (restart = false) return gs_error_rangecheck the when destination wasn't
295
 * large enough without modifying the destination. This is needed for
296
 * compatibility with Adobe implementation of cvs and cvrs, which don't
297
 * change the destination string on failure.
298
 *
299
 * The mem argument is only used for getting the type of structures,
300
 * not for allocating; if it is NULL and full_print != 0, structures will
301
 * print as --(struct)--.
302
 *
303
 * This rather complex API is needed so that a client can call obj_cvp
304
 * repeatedly to print on a stream, which may require suspending at any
305
 * point to handle stream callouts.
306
 */
307
static void ensure_dot(char *, size_t);
308
int
309
obj_cvp(const ref * op, byte * str, uint len, uint * prlen,
310
        int full_print, uint start_pos, const gs_memory_t *mem, bool restart)
311
19.6M
{
312
19.6M
    char buf[256];  /* big enough for any float, double, or struct name */
313
19.6M
    const byte *data = (const byte *)buf;
314
19.6M
    uint size;
315
19.6M
    int code;
316
19.6M
    ref nref;
317
318
19.6M
    if (full_print) {
319
19.2k
        static const char * const type_strings[] = { REF_TYPE_PRINT_STRINGS };
320
321
19.2k
        switch (r_btype(op)) {
322
0
        case t_boolean:
323
468
        case t_integer:
324
468
            break;
325
4
        case t_real: {
326
            /*
327
             * To get fully accurate output results for IEEE
328
             * single-precision floats (24 bits of mantissa), the ANSI %g
329
             * default of 6 digits is not enough; 9 are needed.
330
             * Unfortunately, using %.9g for floats (as opposed to doubles)
331
             * produces unfortunate artifacts such as 0.01 5 mul printing as
332
             * 0.049999997.  Therefore, we print using %g, and if the result
333
             * isn't accurate enough, print again using %.9g.
334
             * Unfortunately, a few PostScript programs 'know' that the
335
             * printed representation of floats fits into 6 digits (e.g.,
336
             * with cvs).  We resolve this by letting cvs, cvrs, and = do
337
             * what the Adobe interpreters appear to do (use %g), and only
338
             * produce accurate output for ==, for which there is no
339
             * analogue of cvs.  What a hack!
340
             */
341
4
            float value = op->value.realval;
342
4
            float scanned;
343
4
            code = gs_snprintf(buf, sizeof(buf), "%g", value);
344
4
            if (code <= 0)
345
0
                return_error(gs_error_undefinedresult);
346
4
            code = sscanf(buf, "%f", &scanned);
347
4
            if (code <= 0)
348
0
                return_error(gs_error_undefinedresult);
349
4
            if (scanned != value)
350
1
                gs_snprintf(buf, sizeof(buf), "%.9g", value);
351
4
            ensure_dot(buf, 256);
352
4
            goto rs;
353
4
        }
354
296
        case t_operator:
355
397
        case t_oparray:
356
397
            code = obj_cvp(op, (byte *)buf + 2, sizeof(buf) - 4, &size, 0, 0, mem, restart);
357
397
            if (code < 0)
358
0
                return code;
359
397
            buf[0] = buf[1] = buf[size + 2] = buf[size + 3] = '-';
360
397
            size += 4;
361
397
            goto nl;
362
3.89k
        case t_name:
363
3.89k
            if (r_has_attr(op, a_executable)) {
364
684
                code = obj_string_data(mem, op, &data, &size);
365
684
                if (code < 0)
366
0
                    return code;
367
684
                goto nl;
368
684
            }
369
3.21k
            if (start_pos > 0)
370
0
                return obj_cvp(op, str, len, prlen, 0, start_pos - 1, mem, restart);
371
3.21k
            if (len < 1)
372
0
                return_error(gs_error_rangecheck);
373
3.21k
            code = obj_cvp(op, str + 1, len - 1, prlen, 0, 0, mem, restart);
374
3.21k
            if (code < 0)
375
0
                return code;
376
3.21k
            str[0] = '/';
377
3.21k
            ++*prlen;
378
3.21k
            return code;
379
0
        case t_null:
380
0
            data = (const byte *)"null";
381
0
            goto rs;
382
14.4k
        case t_string:
383
14.4k
            if (!r_has_attr(op, a_read))
384
0
                goto other;
385
14.4k
            size = r_size(op);
386
14.4k
            {
387
14.4k
                bool truncate = (full_print == 1 && size > CVP_MAX_STRING);
388
14.4k
                stream_cursor_read r;
389
14.4k
                stream_cursor_write w;
390
14.4k
                uint skip;
391
14.4k
                byte *wstr;
392
14.4k
                uint len1;
393
14.4k
                int status = 1;
394
395
14.4k
                if (start_pos == 0) {
396
12.4k
                    if (len < 1)
397
0
                        return_error(gs_error_rangecheck);
398
12.4k
                    str[0] = '(';
399
12.4k
                    skip = 0;
400
12.4k
                    wstr = str + 1;
401
12.4k
                } else {
402
2.02k
                    skip = start_pos - 1;
403
2.02k
                    wstr = str;
404
2.02k
                }
405
14.4k
                len1 = len + (str - wstr);
406
14.4k
                stream_cursor_read_init(&r, op->value.const_bytes, truncate ? CVP_MAX_STRING : size);
407
408
15.6k
                while (skip && status == 1) {
409
3.18k
                    uint written;
410
411
3.18k
                    stream_cursor_write_init(&w, (byte *)buf, min(skip + len1, sizeof(buf)));
412
3.18k
                    status = s_PSSE_template.process(NULL, &r, &w, false);
413
                    /* +1 accounts for crazy w.ptr initialisation - see stream_cursor_write_init() */
414
3.18k
                    written = (w.ptr - ((byte *)buf)) + 1;
415
3.18k
                    if (written > skip) {
416
2.01k
                        written -= skip;
417
2.01k
                        memcpy(wstr, buf + skip, written);
418
2.01k
                        wstr += written;
419
2.01k
                        skip = 0;
420
2.01k
                        break;
421
2.01k
                    }
422
1.17k
                    skip -= written;
423
1.17k
                }
424
                /*
425
                 * We can reach here with status == 0 (and skip != 0) if
426
                 * start_pos lies within the trailing ")" or  "...)".
427
                 */
428
14.4k
                if (status == 0) {
429
#ifdef DEBUG
430
                    if (skip > (truncate ? 4 : 1)) {
431
                        return_error(gs_error_Fatal);
432
                    }
433
#endif
434
252
                }
435
14.4k
                stream_cursor_write_init(&w, (byte *)wstr, (size_t)((str + len) - wstr));
436
14.4k
                if (status == 1)
437
14.2k
                    status = s_PSSE_template.process(NULL, &r, &w, false);
438
14.4k
                *prlen = w.ptr - (str - 1);
439
14.4k
                if (status != 0)
440
2.01k
                    return 1;
441
12.4k
                if (truncate) {
442
72
                    if (len - *prlen < 4 - skip)
443
1
                        return 1;
444
71
                    memcpy(w.ptr + 1, &"...)"[skip], 4 - skip);
445
71
                    *prlen += 4 - skip;
446
12.3k
                } else {
447
12.3k
                    if (len - *prlen < 1 - skip)
448
10
                        return 1;
449
12.3k
                    if (!skip) {
450
12.3k
                        w.ptr[1] = ')';
451
12.3k
                        *prlen += 1;
452
12.3k
                    }
453
12.3k
                }
454
12.4k
            }
455
12.4k
            return 0;
456
0
        case t_astruct:
457
0
        case t_struct:
458
0
            if (r_is_foreign(op)) {
459
                /* gs_object_type may not work. */
460
0
                data = (const byte *)"-foreign-struct-";
461
0
                goto rs;
462
0
            }
463
0
            if (!mem) {
464
0
                data = (const byte *)"-(struct)-";
465
0
                goto rs;
466
0
            }
467
0
            data = (const byte *)
468
0
                gs_struct_type_name_string(
469
0
                                gs_object_type(mem,
470
0
                                    (const obj_header_t *)op->value.pstruct));
471
0
            size = strlen((const char *)data);
472
0
            if (size > 4 && !memcmp(data + size - 4, "type", 4))
473
0
                size -= 4;
474
0
            if (size > sizeof(buf) - 3)
475
0
                return_error(gs_error_rangecheck);
476
0
            buf[0] = '-';
477
0
            memcpy(buf + 1, data, size);
478
0
            buf[size + 1] = '-';
479
0
            size += 2;
480
0
            data = (const byte *)buf;
481
0
            goto nl;
482
0
        case t_pdfctx:
483
0
            data = (const byte *)"-pdfcontext-";
484
0
            goto rs;
485
1
        default:
486
1
other:
487
1
            {
488
1
                int rtype = r_btype(op);
489
490
1
                if (rtype >= countof(type_strings))
491
0
                    return_error(gs_error_rangecheck);
492
1
                data = (const byte *)type_strings[rtype];
493
1
                if (data == 0)
494
0
                    return_error(gs_error_rangecheck);
495
1
            }
496
1
            goto rs;
497
19.2k
        }
498
19.2k
    }
499
    /* full_print = 0 */
500
19.6M
    switch (r_btype(op)) {
501
2.36k
    case t_boolean:
502
2.36k
        data = (const byte *)(op->value.boolval ? "true" : "false");
503
2.36k
        break;
504
652k
    case t_integer:
505
652k
        gs_snprintf(buf, sizeof(buf), "%"PRIpsint, op->value.intval);
506
652k
        break;
507
133k
    case t_string:
508
133k
        check_read(*op);
509
        /* falls through */
510
12.1M
    case t_name:
511
12.1M
        code = obj_string_data(mem, op, &data, &size);
512
12.1M
        if (code < 0)
513
0
            return code;
514
12.1M
        goto nl;
515
12.1M
    case t_oparray: {
516
5.80M
        uint index = op_index(op);
517
5.80M
        const op_array_table *opt = get_op_array(mem, index);
518
519
5.80M
        name_index_ref(mem, opt->nx_table[index - opt->base_index], &nref);
520
5.80M
        name_string_ref(mem, &nref, &nref);
521
5.80M
        code = obj_string_data(mem, &nref, &data, &size);
522
5.80M
        if (code < 0)
523
0
            return code;
524
5.80M
        goto nl;
525
5.80M
    }
526
5.80M
    case t_operator: {
527
        /* Recover the name from the initialization table. */
528
154k
        uint index = op_index(op);
529
530
        /*
531
         * Check the validity of the index.  (An out-of-bounds index
532
         * is only possible when examining an invalid object using
533
         * the debugger.)
534
         */
535
154k
        if (index > 0 && index < op_def_count) {
536
154k
            data = (const byte *)(op_index_def(index)->oname + 1);
537
154k
            break;
538
154k
        }
539
        /* Internal operator, no name. */
540
#if defined(DEBUG) && DEBUG != 0
541
        gs_snprintf(buf, sizeof(buf), "@"PRI_INTPTR, (intptr_t) op->value.opproc);
542
#else
543
0
        gs_snprintf(buf, sizeof(buf), "@anonymous_operator", (intptr_t) op->value.opproc);
544
0
#endif
545
0
        break;
546
154k
    }
547
28.8k
    case t_real:
548
        /*
549
         * The value 0.0001 is a boundary case that the Adobe interpreters
550
         * print in f-format but at least some gs versions print in
551
         * e-format, presumably because of differences in the underlying C
552
         * library implementation.  Work around this here.
553
         */
554
28.8k
        if (op->value.realval == (float)0.0001) {
555
7
            strncpy(buf, "0.0001", 256);
556
28.8k
        } else {
557
28.8k
            gs_snprintf(buf, sizeof(buf), "%g", op->value.realval);
558
28.8k
        }
559
28.8k
        ensure_dot(buf, 256);
560
28.8k
        break;
561
862k
    default:
562
862k
        data = (const byte *)"--nostringval--";
563
19.6M
    }
564
1.70M
rs: size = strlen((const char *)data);
565
19.6M
nl: if (size < start_pos)
566
0
        return_error(gs_error_rangecheck);
567
19.6M
    if (!restart && size > len)
568
0
        return_error(gs_error_rangecheck);
569
19.6M
    size -= start_pos;
570
19.6M
    *prlen = min(size, len);
571
19.6M
    memmove(str, data + start_pos, *prlen);
572
19.6M
    return (size > len);
573
19.6M
}
574
/*
575
 * Make sure the converted form of a real number has at least one of an 'e'
576
 * or a decimal point, so it won't be mistaken for an integer.
577
 * Re-format the exponent to satisfy Genoa CET test.
578
 */
579
static void
580
ensure_dot(char *buf, size_t buflen)
581
28.8k
{
582
28.8k
    char *pe = strchr(buf, 'e');
583
28.8k
    if (pe) {
584
25.4k
        int i;
585
25.4k
        (void)sscanf(pe + 1, "%d", &i);
586
25.4k
        buflen -= (size_t)(pe - buf);
587
        /* MSVC .net 2005 express doesn't support "%+02d" */
588
25.4k
        if (i >= 0)
589
11.2k
            gs_snprintf(pe + 1, buflen, "+%02d", i);
590
14.1k
        else
591
14.1k
            gs_snprintf(pe + 1, buflen, "-%02d", -i);
592
25.4k
    } else if (strchr(buf, '.') == NULL) {
593
3.23k
        strcat(buf, ".0");
594
3.23k
    }
595
28.8k
}
596
597
/*
598
 * Create a printable representation of an object, a la cvs and =.  Return 0
599
 * if OK, gs_error_rangecheck if the destination wasn't large enough,
600
 * gs_error_invalidaccess if the object's contents weren't readable.  If pchars !=
601
 * NULL, then if the object was a string or name, store a pointer to its
602
 * characters in *pchars even if it was too large; otherwise, set *pchars =
603
 * str.  In any case, store the length in *prlen.
604
 */
605
int
606
obj_cvs(const gs_memory_t *mem, const ref * op, byte * str, uint len, uint * prlen,
607
        const byte ** pchars)
608
18.5M
{
609
18.5M
    int code = obj_cvp(op, str, len, prlen, 0, 0, mem, false);  /* NB: NULL memptr */
610
611
18.5M
    if (code == 1) {
612
0
        if (pchars)
613
0
            obj_string_data(mem, op, pchars, prlen);
614
0
        return gs_note_error(gs_error_rangecheck);
615
18.5M
    } else {
616
18.5M
        if (pchars)
617
18.5M
          *pchars = str;
618
18.5M
        return code;
619
18.5M
    }
620
18.5M
}
621
622
/* Find the index of an operator that doesn't have one stored in it. */
623
ushort
624
op_find_index(const ref * pref /* t_operator */ )
625
211k
{
626
211k
    op_proc_t proc = real_opproc(pref);
627
211k
    const op_def *const *opp = op_defs_all;
628
211k
    const op_def *const *opend = opp + (op_def_count / OP_DEFS_MAX_SIZE);
629
630
3.88M
    for (; opp < opend; ++opp) {
631
3.88M
        const op_def *def = *opp;
632
633
25.0M
        for (; def->oname != 0; ++def)
634
21.3M
            if (def->proc == proc)
635
211k
                return (opp - op_defs_all) * OP_DEFS_MAX_SIZE + (def - *opp);
636
3.88M
    }
637
    /* Lookup failed!  This isn't possible.... */
638
0
    return 0;
639
211k
}
640
641
/*
642
 * Convert an operator index to an operator or oparray ref.
643
 * This is only used for debugging and for 'get' from packed arrays,
644
 * so it doesn't have to be very fast.
645
 */
646
void
647
op_index_ref(const gs_memory_t *mem, uint index, ref * pref)
648
13.6M
{
649
13.6M
    const op_array_table *opt;
650
651
13.6M
    if (op_index_is_operator(index)) {
652
5.99M
        make_oper(pref, index, op_index_proc(index));
653
5.99M
        return;
654
5.99M
    }
655
7.64M
    opt = get_op_array(mem, index);
656
7.64M
    make_tasv(pref, t_oparray, opt->attrs, index,
657
7.64M
              const_refs, (opt->table.value.const_refs
658
7.64M
                           + index - opt->base_index));
659
7.64M
}
660
661
/* Get an element from an array of some kind. */
662
/* This is also used to index into Encoding vectors, */
663
/* the error name vector, etc. */
664
int
665
array_get(const gs_memory_t *mem, const ref * aref, long index_long, ref * pref)
666
518M
{
667
518M
    if ((ulong)index_long >= r_size(aref))
668
7
        return_error(gs_error_rangecheck);
669
518M
    switch (r_type(aref)) {
670
366M
        case t_array:
671
366M
            {
672
366M
                const ref *pvalue = aref->value.refs + index_long;
673
674
366M
                ref_assign(pref, pvalue);
675
366M
            }
676
366M
            break;
677
94.9M
        case t_mixedarray:
678
94.9M
            {
679
94.9M
                const ref_packed *packed = aref->value.packed;
680
94.9M
                uint index = (uint)index_long;
681
682
1.57G
                for (; index--;)
683
1.48G
                    packed = packed_next(packed);
684
94.9M
                packed_get(mem, packed, pref);
685
94.9M
            }
686
94.9M
            break;
687
56.6M
        case t_shortarray:
688
56.6M
            {
689
56.6M
                const ref_packed *packed = aref->value.packed + index_long;
690
691
56.6M
                packed_get(mem, packed, pref);
692
56.6M
            }
693
56.6M
            break;
694
0
        default:
695
0
            return_error(gs_error_typecheck);
696
518M
    }
697
518M
    return 0;
698
518M
}
699
700
/* Get an element from a packed array. */
701
/* (This works for ordinary arrays too.) */
702
/* Source and destination are allowed to overlap if the source is packed, */
703
/* or if they are identical. */
704
void
705
packed_get(const gs_memory_t *mem, const ref_packed * packed, ref * pref)
706
217M
{
707
217M
    const ref_packed elt = *packed;
708
217M
    uint value = elt & packed_value_mask;
709
710
217M
    switch (elt >> r_packed_type_shift) {
711
0
        default:    /* (shouldn't happen) */
712
0
            make_null(pref);
713
0
            break;
714
6.00M
        case pt_executable_operator:
715
6.00M
            op_index_ref(mem, value, pref);
716
6.00M
            break;
717
38.6M
        case pt_integer:
718
38.6M
            make_int(pref, (ps_int)value + packed_min_intval);
719
38.6M
            break;
720
48.2M
        case pt_literal_name:
721
48.2M
            name_index_ref(mem, value, pref);
722
48.2M
            break;
723
118M
        case pt_executable_name:
724
118M
            name_index_ref(mem, value, pref);
725
118M
            r_set_attrs(pref, a_executable);
726
118M
            break;
727
7.02M
        case pt_full_ref:
728
7.02M
        case pt_full_ref + 1:
729
7.02M
            ref_assign(pref, (const ref *)packed);
730
217M
    }
731
217M
}
732
733
/* Check to make sure an interval contains no object references */
734
/* to a space younger than a given one. */
735
/* Return 0 or gs_error_invalidaccess. */
736
int
737
refs_check_space(const ref * bot, uint size, uint space)
738
39.4M
{
739
118M
    for (; size--; bot++)
740
79.1M
        store_check_space(space, bot);
741
39.4M
    return 0;
742
39.4M
}
743
744
/* ------ String utilities ------ */
745
746
/* Convert a C string to a Ghostscript string */
747
int
748
string_to_ref(const char *cstr, ref * pref, gs_ref_memory_t * mem,
749
              client_name_t cname)
750
2.25k
{
751
2.25k
    uint size = strlen(cstr);
752
2.25k
    int code = gs_alloc_string_ref(mem, pref, a_all, size, cname);
753
754
2.25k
    if (code < 0)
755
0
        return code;
756
2.25k
    memcpy(pref->value.bytes, cstr, size);
757
2.25k
    return 0;
758
2.25k
}
759
760
/* Convert a Ghostscript string to a C string. */
761
/* Return 0 iff the buffer can't be allocated. */
762
char *
763
ref_to_string(const ref * pref, gs_memory_t * mem, client_name_t cname)
764
71.0k
{
765
71.0k
    uint size = r_size(pref);
766
71.0k
    char *str = (char *)gs_alloc_string(mem, size + 1, cname);
767
768
71.0k
    if (str == 0)
769
0
        return 0;
770
71.0k
    memcpy(str, (const char *)pref->value.bytes, size);
771
71.0k
    str[size] = 0;
772
71.0k
    return str;
773
71.0k
}
774
775
/* ------ Operand utilities ------ */
776
777
/* Get N numeric operands from the stack or an array. */
778
/* Return a bit-mask indicating which ones are integers, */
779
/* or a (negative) error indication. */
780
/* The 1-bit in the bit-mask refers to the first operand. */
781
/* Store float versions of the operands at pval. */
782
/* The stack underflow check (check for t__invalid) is harmless */
783
/* if the operands come from somewhere other than the stack. */
784
int
785
num_params(const ref * op, int count, double *pval)
786
3.86M
{
787
3.86M
    int mask = 0;
788
789
3.86M
    pval += count;
790
17.1M
    while (--count >= 0) {
791
13.2M
        mask <<= 1;
792
13.2M
        switch (r_type(op)) {
793
6.58M
            case t_real:
794
6.58M
                *--pval = op->value.realval;
795
6.58M
                break;
796
6.68M
            case t_integer:
797
6.68M
                *--pval = (double)op->value.intval;
798
6.68M
                mask++;
799
6.68M
                break;
800
4
            case t__invalid:
801
4
                return_error(gs_error_stackunderflow);
802
20
            default:
803
20
                return_error(gs_error_typecheck);
804
13.2M
        }
805
13.2M
        op--;
806
13.2M
    }
807
    /* If count is very large, mask might overflow. */
808
    /* In this case we clearly don't care about the value of mask. */
809
3.86M
    return (mask < 0 ? 0 : mask);
810
3.86M
}
811
/* float_params doesn't bother to keep track of the mask. */
812
int
813
float_params(const ref * op, int count, float *pval)
814
1.76M
{
815
7.28M
    for (pval += count; --count >= 0; --op)
816
5.51M
        switch (r_type(op)) {
817
627k
            case t_real:
818
627k
                *--pval = op->value.realval;
819
627k
                break;
820
4.88M
            case t_integer:
821
4.88M
                *--pval = (float)op->value.intval;
822
4.88M
                break;
823
4
            case t__invalid:
824
4
                return_error(gs_error_stackunderflow);
825
2
            default:
826
2
                return_error(gs_error_typecheck);
827
5.51M
        }
828
1.76M
    return 0;
829
1.76M
}
830
831
/* Get N numeric parameters (as floating point numbers) from an array */
832
int
833
process_float_array(const gs_memory_t *mem, const ref * parray, int count, float * pval)
834
55.9k
{
835
55.9k
    int         code = 0, indx0 = 0;
836
837
    /* we assume parray is an array of some type, of adequate length */
838
55.9k
    if (r_has_type(parray, t_array))
839
55.9k
        return float_params(parray->value.refs + count - 1, count, pval);
840
841
    /* short/mixed array; convert the entries to refs */
842
0
    while (count > 0 && code >= 0) {
843
0
        int     i, subcount;
844
0
        ref     ref_buff[20];   /* 20 is arbitrary */
845
846
0
        subcount = (count > countof(ref_buff) ? countof(ref_buff) : count);
847
0
        for (i = 0; i < subcount && code >= 0; i++)
848
0
            code = array_get(mem, parray, (long)(i + indx0), &ref_buff[i]);
849
0
        if (code >= 0)
850
0
            code = float_params(ref_buff + subcount - 1, subcount, pval);
851
0
        count -= subcount;
852
0
        pval += subcount;
853
0
        indx0 += subcount;
854
0
    }
855
856
0
    return code;
857
55.9k
}
858
859
/* Get a single real parameter. */
860
/* The only possible errors are gs_error_typecheck and gs_error_stackunderflow. */
861
/* If an error is returned, the return value is not updated. */
862
int
863
real_param(const ref * op, double *pparam)
864
12.3M
{
865
12.3M
    switch (r_type(op)) {
866
4.54M
        case t_integer:
867
4.54M
            *pparam = (double)op->value.intval;
868
4.54M
            break;
869
7.77M
        case t_real:
870
7.77M
            *pparam = op->value.realval;
871
7.77M
            break;
872
1
        case t__invalid:
873
1
            return_error(gs_error_stackunderflow);
874
13
        default:
875
13
            return_error(gs_error_typecheck);
876
12.3M
    }
877
12.3M
    return 0;
878
12.3M
}
879
int
880
float_param(const ref * op, float *pparam)
881
91.6k
{
882
91.6k
    double dval;
883
91.6k
    int code = real_param(op, &dval);
884
885
91.6k
    if (code >= 0)
886
91.6k
        *pparam = (float)dval; /* can't overflow */
887
91.6k
    return code;
888
91.6k
}
889
890
/* Get an integer parameter in a given range. */
891
int
892
int_param(const ref * op, int max_value, int *pparam)
893
60
{
894
60
    check_int_leu(*op, max_value);
895
57
    *pparam = (int)op->value.intval;
896
57
    return 0;
897
60
}
898
899
/* Make real values on the operand stack. */
900
int
901
make_reals(ref * op, const double *pval, int count)
902
2.30k
{
903
    /* This should return gs_error_limitcheck if any real is too large */
904
    /* to fit into a float on the stack. */
905
11.5k
    for (; count--; op++, pval++)
906
9.23k
        make_real(op, *pval);
907
2.30k
    return 0;
908
2.30k
}
909
int
910
make_floats(ref * op, const float *pval, int count)
911
30.3k
{
912
    /* This should return gs_error_undefinedresult for infinities. */
913
148k
    for (; count--; op++, pval++)
914
118k
        make_real(op, *pval);
915
30.3k
    return 0;
916
30.3k
}
917
918
/* Compute the error code when check_proc fails. */
919
/* Note that the client, not this procedure, uses return_error. */
920
/* The stack underflow check is harmless in the off-stack case. */
921
int
922
check_proc_failed(const ref * pref)
923
18
{
924
18
    if (r_is_array(pref)) {
925
1
        if (r_has_attr(pref, a_executable))
926
0
            return gs_error_invalidaccess;
927
1
        else
928
1
            return gs_error_typecheck;
929
17
    } else {
930
17
        if (r_has_type(pref, t__invalid))
931
3
            return gs_error_stackunderflow;
932
14
        else
933
14
            return gs_error_typecheck;
934
17
    }
935
18
}
936
937
/* Compute the error code when a type check on the stack fails. */
938
/* Note that the client, not this procedure, uses return_error. */
939
int
940
check_type_failed(const ref * op)
941
5.78M
{
942
5.78M
    return (r_has_type(op, t__invalid) ? gs_error_stackunderflow : gs_error_typecheck);
943
5.78M
}
944
945
/* ------ Matrix utilities ------ */
946
947
/* Read a matrix operand. */
948
/* Return 0 if OK, error code if not. */
949
int
950
read_matrix(const gs_memory_t *mem, const ref * op, gs_matrix * pmat)
951
84.0k
{
952
84.0k
    int code;
953
84.0k
    ref values[6];
954
84.0k
    const ref *pvalues;
955
956
84.0k
    switch (r_type(op)) {
957
84.0k
        case t_array:
958
84.0k
            pvalues = op->value.refs;
959
84.0k
            break;
960
0
        case t_mixedarray:
961
1
        case t_shortarray:
962
1
            {
963
1
                int i;
964
965
7
                for (i = 0; i < 6; ++i) {
966
6
                    code = array_get(mem, op, (long)i, &values[i]);
967
6
                    if (code < 0)
968
0
                        return code;
969
6
                }
970
1
                pvalues = values;
971
1
            }
972
0
            break;
973
3
        default:
974
3
            return_op_typecheck(op);
975
84.0k
    }
976
84.0k
    check_read(*op);
977
84.0k
    if (r_size(op) != 6)
978
1
        return_error(gs_error_rangecheck);
979
84.0k
    code = float_params(pvalues + 5, 6, (float *)pmat);
980
84.0k
    return (code < 0 ? code : 0);
981
84.0k
}
982
983
/* Write a matrix operand. */
984
/* Return 0 if OK, error code if not. */
985
int
986
write_matrix_in(ref * op, const gs_matrix * pmat, gs_dual_memory_t *idmemory,
987
                gs_ref_memory_t *imem)
988
65.6k
{
989
65.6k
    ref *aptr;
990
65.6k
    const float *pel;
991
65.6k
    int i;
992
993
65.6k
    check_write_type(*op, t_array);
994
65.6k
    if (r_size(op) != 6)
995
0
        return_error(gs_error_rangecheck);
996
65.6k
    aptr = op->value.refs;
997
65.6k
    pel = (const float *)pmat;
998
459k
    for (i = 5; i >= 0; i--, aptr++, pel++) {
999
393k
        if (idmemory) {
1000
393k
            ref_save(op, aptr, "write_matrix");
1001
393k
            make_real_new(aptr, *pel);
1002
393k
        } else {
1003
132
            make_tav(aptr, t_real, imemory_new_mask(imem), realval, *pel);
1004
132
        }
1005
393k
    }
1006
65.6k
    return 0;
1007
65.6k
}