Coverage Report

Created: 2025-06-10 06:58

/src/ghostpdl/base/gsfunc4.c
Line
Count
Source (jump to first uncovered line)
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
/* Implementation of FunctionType 4 (PostScript Calculator) Functions */
18
#include "math_.h"
19
#include "memory_.h"
20
#include "gx.h"
21
#include "gserrors.h"
22
#include "gsdsrc.h"
23
#include "gsfunc4.h"
24
#include "gxfarith.h"
25
#include "gxfunc.h"
26
#include "stream.h"
27
#include "strimpl.h"
28
#include "sfilter.h"    /* for SubFileDecode */
29
#include "spprint.h"
30
#include "stream.h"
31
32
typedef struct gs_function_PtCr_s {
33
    gs_function_head_t head;
34
    gs_function_PtCr_params_t params;
35
    /* Define a bogus DataSource for get_function_info. */
36
    gs_data_source_t data_source;
37
} gs_function_PtCr_t;
38
39
/* GC descriptor */
40
private_st_function_PtCr();
41
42
/* Define the maximum stack depth. */
43
402k
#define MAX_VSTACK 256    /* Max 100 is enough per PDF spec, but we use this
44
                                 * for DeviceN handling. Must be at least as large
45
                                 * as the number of components
46
                                 */
47
48
/* Define the structure of values on the stack. */
49
typedef enum {
50
    CVT_NONE = 0, /* empty stack slot */
51
    CVT_BOOL,
52
    CVT_INT,
53
    CVT_FLOAT
54
} calc_value_type_t;
55
typedef struct calc_value_s {
56
    calc_value_type_t type;
57
    union {
58
        int i;      /* also used for Boolean */
59
        float f;
60
    } value;
61
} calc_value_t;
62
63
/* Store a float. */
64
static inline void
65
store_float(calc_value_t *vsp, double f)
66
129k
{
67
129k
    vsp->value.f = f;
68
129k
    vsp->type = CVT_FLOAT;
69
129k
}
70
71
/*
72
 * Define extended opcodes with typed operands.  We use the original
73
 * opcodes for the floating-point case.
74
 */
75
typedef enum {
76
77
        /* Typed variants */
78
79
    PtCr_abs_int = PtCr_NUM_OPCODES,
80
    PtCr_add_int,
81
    PtCr_mul_int,
82
    PtCr_neg_int,
83
    PtCr_not_bool,    /* default is int */
84
    PtCr_sub_int,
85
    PtCr_eq_int,
86
    PtCr_ge_int,
87
    PtCr_gt_int,
88
    PtCr_le_int,
89
    PtCr_lt_int,
90
    PtCr_ne_int,
91
92
        /* Coerce and re-dispatch */
93
94
    PtCr_int_to_float,
95
    PtCr_2nd_int_to_float,
96
    PtCr_int2_to_float,
97
98
        /* Miscellaneous */
99
100
    PtCr_no_op,
101
    PtCr_typecheck
102
103
} gs_PtCr_typed_opcode_t;
104
105
/* Evaluate a PostScript Calculator function. */
106
static int
107
fn_PtCr_evaluate(const gs_function_t *pfn_common, const float *in, float *out)
108
37.1k
{
109
37.1k
    const gs_function_PtCr_t *pfn = (const gs_function_PtCr_t *)pfn_common;
110
37.1k
    calc_value_t vstack_buf[2 + MAX_VSTACK + 1];
111
37.1k
    calc_value_t *vstack = &vstack_buf[1];
112
37.1k
    calc_value_t *vsp = vstack + pfn->params.m;
113
37.1k
    const byte *p = pfn->params.ops.data;
114
37.1k
    int repeat_count[MAX_PSC_FUNCTION_NESTING];
115
37.1k
    int repeat_proc_size[MAX_PSC_FUNCTION_NESTING];
116
37.1k
    int repeat_nesting_level = -1;
117
37.1k
    int i;
118
119
    /*
120
     * Define the table for mapping explicit opcodes to typed opcodes.
121
     * We index this table with the opcode and the types of the top 2
122
     * values on the stack.
123
     */
124
37.1k
    static const struct op_defn_s {
125
37.1k
        byte opcode[16];  /* 4 * type[-1] + type[0] */
126
37.1k
    } op_defn_table[] = {
127
        /* Keep this consistent with opcodes in gsfunc4.h! */
128
129
2.71M
#define O4(op) op,op,op,op
130
5.98M
#define E PtCr_typecheck
131
1.52M
#define E4 O4(E)
132
37.1k
#define N PtCr_no_op
133
        /* 0-operand operators */
134
37.1k
#define OP_NONE(op)\
135
297k
  {{O4(op), O4(op), O4(op), O4(op)}}
136
        /* 1-operand operators */
137
37.1k
#define OP1(b, i, f)\
138
742k
  {{E,b,i,f, E,b,i,f, E,b,i,f, E,b,i,f}}
139
37.1k
#define OP_NUM1(i, f)\
140
297k
  OP1(E, i, f)
141
37.1k
#define OP_MATH1(f)\
142
185k
  OP1(E, PtCr_int_to_float, f)
143
37.1k
#define OP_ANY1(op)\
144
74.2k
  OP1(op, op, op)
145
        /* 2-operand operators */
146
37.1k
#define OP_NUM2(i, f)\
147
260k
  {{E4, E4, E,E,i,PtCr_2nd_int_to_float, E,E,PtCr_int_to_float,f}}
148
37.1k
#define OP_INT_BOOL2(i)\
149
111k
  {{E4, E,i,i,E, E,i,i,E, E4}}
150
37.1k
#define OP_MATH2(f)\
151
111k
  {{E4, E4, E,E,PtCr_int2_to_float,PtCr_2nd_int_to_float,\
152
111k
    E,E,PtCr_int_to_float,f}}
153
37.1k
#define OP_INT2(i)\
154
148k
  {{E4, E4, E,E,i,E, E4}}
155
37.1k
#define OP_REL2(i, f)\
156
74.2k
  {{E4, E,i,E,E, E,E,i,PtCr_2nd_int_to_float, E,E,PtCr_int_to_float,f}}
157
37.1k
#define OP_ANY2(op)\
158
37.1k
  {{E4, E,op,op,op, E,op,op,op, E,op,op,op}}
159
160
    /* Arithmetic operators */
161
162
37.1k
        OP_NUM1(PtCr_abs_int, PtCr_abs), /* abs */
163
37.1k
        OP_NUM2(PtCr_add_int, PtCr_add), /* add */
164
37.1k
        OP_INT_BOOL2(PtCr_and),  /* and */
165
37.1k
        OP_MATH2(PtCr_atan),  /* atan */
166
37.1k
        OP_INT2(PtCr_bitshift),  /* bitshift */
167
37.1k
        OP_NUM1(N, PtCr_ceiling),  /* ceiling */
168
37.1k
        OP_MATH1(PtCr_cos), /* cos */
169
37.1k
        OP_NUM1(N, PtCr_cvi),  /* cvi */
170
37.1k
        OP_NUM1(PtCr_int_to_float, N), /* cvr */
171
37.1k
        OP_MATH2(PtCr_div), /* div */
172
37.1k
        OP_MATH2(PtCr_exp), /* exp */
173
37.1k
        OP_NUM1(N, PtCr_floor),  /* floor */
174
37.1k
        OP_INT2(PtCr_idiv),  /* idiv */
175
37.1k
        OP_MATH1(PtCr_ln),  /* ln */
176
37.1k
        OP_MATH1(PtCr_log), /* log */
177
37.1k
        OP_INT2(PtCr_mod), /* mod */
178
37.1k
        OP_NUM2(PtCr_mul_int, PtCr_mul), /* mul */
179
37.1k
        OP_NUM1(PtCr_neg_int, PtCr_neg), /* neg */
180
37.1k
        OP1(PtCr_not, PtCr_not, E),  /* not */
181
37.1k
        OP_INT_BOOL2(PtCr_or),  /* or */
182
37.1k
        OP_NUM1(N, PtCr_round),  /* round */
183
37.1k
        OP_MATH1(PtCr_sin), /* sin */
184
37.1k
        OP_MATH1(PtCr_sqrt),  /* sqrt */
185
37.1k
        OP_NUM2(PtCr_sub_int, PtCr_sub), /* sub */
186
37.1k
        OP_NUM1(N, PtCr_truncate), /* truncate */
187
37.1k
        OP_INT_BOOL2(PtCr_xor),  /* xor */
188
189
    /* Comparison operators */
190
191
37.1k
        OP_REL2(PtCr_eq_int, PtCr_eq), /* eq */
192
37.1k
        OP_NUM2(PtCr_ge_int, PtCr_ge), /* ge */
193
37.1k
        OP_NUM2(PtCr_gt_int, PtCr_gt), /* gt */
194
37.1k
        OP_NUM2(PtCr_le_int, PtCr_le), /* le */
195
37.1k
        OP_NUM2(PtCr_lt_int, PtCr_lt), /* lt */
196
37.1k
        OP_REL2(PtCr_ne_int, PtCr_ne), /* ne */
197
198
    /* Stack operators */
199
200
37.1k
        OP1(E, PtCr_copy, E),  /* copy */
201
37.1k
        OP_ANY1(PtCr_dup), /* dup */
202
37.1k
        OP_ANY2(PtCr_exch),  /* exch */
203
37.1k
        OP1(E, PtCr_index, E), /* index */
204
37.1k
        OP_ANY1(PtCr_pop), /* pop */
205
37.1k
        OP_INT2(PtCr_roll),  /* roll */
206
207
    /* Constants */
208
209
37.1k
        OP_NONE(PtCr_byte),    /* byte */
210
37.1k
        OP_NONE(PtCr_int),   /* int */
211
37.1k
        OP_NONE(PtCr_float),   /* float */
212
37.1k
        OP_NONE(PtCr_true),    /* true */
213
37.1k
        OP_NONE(PtCr_false),   /* false */
214
215
    /* Special */
216
217
37.1k
        OP1(PtCr_if, E, E),    /* if */
218
37.1k
        OP_NONE(PtCr_else),    /* else */
219
37.1k
        OP_NONE(PtCr_return),    /* return */
220
37.1k
        OP1(E, PtCr_repeat, E),    /* repeat */
221
37.1k
        OP_NONE(PtCr_repeat_end) /* repeat_end */
222
37.1k
    };
223
224
37.1k
    memset(repeat_count, 0x00, MAX_PSC_FUNCTION_NESTING * sizeof(int));
225
37.1k
    memset(repeat_proc_size, 0x00, MAX_PSC_FUNCTION_NESTING * sizeof(int));
226
227
37.1k
    vstack[-1].type = CVT_NONE;  /* for type dispatch in empty stack case */
228
37.1k
    vstack[0].type = CVT_NONE;  /* catch underflow */
229
101k
    for (i = 0; i < pfn->params.m; ++i)
230
64.5k
        store_float(&vstack[i + 1], in[i]);
231
232
678k
    for (; ; ) {
233
678k
        int code, n;
234
235
678k
        switch (op_defn_table[*p++].opcode[(vsp[-1].type << 2) + vsp->type]) {
236
237
            /* Miscellaneous */
238
239
0
        case PtCr_no_op:
240
0
            continue;
241
4
        case PtCr_typecheck:
242
4
            return_error(gs_error_typecheck);
243
244
            /* Coerce and re-dispatch */
245
246
41.1k
        case PtCr_int_to_float:
247
41.1k
            store_float(vsp, (double)vsp->value.i);
248
41.1k
            --p; continue;
249
0
        case PtCr_int2_to_float:
250
0
            store_float(vsp, (double)vsp->value.i);
251
            /* fall through */
252
23.4k
        case PtCr_2nd_int_to_float:
253
23.4k
            store_float(vsp - 1, (double)vsp[-1].value.i);
254
23.4k
            --p; continue;
255
256
            /* Arithmetic operators */
257
258
54.5k
        case PtCr_abs:
259
54.5k
            vsp->value.f = fabs(vsp->value.f);
260
54.5k
            continue;
261
0
        case PtCr_add_int: {
262
0
            int int1 = vsp[-1].value.i, int2 = vsp->value.i;
263
264
0
            if ((int1 ^ int2) >= 0 && ((int1 + int2) ^ int1) < 0)
265
0
                store_float(vsp - 1, (double)int1 + int2);
266
0
            else
267
0
                vsp[-1].value.i = int1 + int2;
268
0
            --vsp; continue;
269
0
        }
270
54.5k
        case PtCr_add:
271
54.5k
            vsp[-1].value.f += vsp->value.f;
272
54.5k
            --vsp; continue;
273
0
        case PtCr_and:
274
0
            vsp[-1].value.i &= vsp->value.i;
275
0
            --vsp; continue;
276
49
        case PtCr_atan: {
277
49
            double result;
278
279
49
            code = gs_atan2_degrees(vsp[-1].value.f, vsp->value.f,
280
49
                                    &result);
281
49
            if (code < 0)
282
0
                return code;
283
49
            vsp[-1].value.f = result;
284
49
            --vsp; continue;
285
49
        }
286
0
        case PtCr_bitshift:
287
0
#define MAX_SHIFT (ARCH_SIZEOF_INT * 8 - 1)
288
0
            if (vsp->value.i < -MAX_SHIFT || vsp->value.i > MAX_SHIFT)
289
0
                vsp[-1].value.i = 0;
290
0
#undef MAX_SHIFT
291
0
            else if ((n = vsp->value.i) < 0)
292
0
                vsp[-1].value.i = ((uint)(vsp[-1].value.i)) >> -n;
293
0
            else
294
0
                vsp[-1].value.i <<= n;
295
0
            --vsp; continue;
296
0
        case PtCr_ceiling:
297
0
            vsp->value.f = ceil(vsp->value.f);
298
0
            continue;
299
49
        case PtCr_cos:
300
49
            vsp->value.f = gs_cos_degrees(vsp->value.f);
301
49
            continue;
302
0
        case PtCr_cvi:
303
0
        {
304
           /* Strictly speaking assigning one element of union
305
            * to another, overlapping element of a different size is
306
            * undefined behavior, hence assign to an intermediate variable
307
            */
308
0
            int int1 = (int)(vsp->value.f);
309
0
            vsp->value.i = int1;
310
0
            vsp->type = CVT_INT;
311
0
            continue;
312
49
        }
313
0
        case PtCr_cvr:
314
0
            continue;  /* prepare handled it */
315
49
        case PtCr_div:
316
49
            if (vsp->value.f == 0)
317
0
                return_error(gs_error_undefinedresult);
318
49
            vsp[-1].value.f /= vsp->value.f;
319
49
            --vsp; continue;
320
0
        case PtCr_exp:
321
0
            vsp[-1].value.f = pow(vsp[-1].value.f, vsp->value.f);
322
0
            --vsp; continue;
323
0
        case PtCr_floor:
324
0
            vsp->value.f = floor(vsp->value.f);
325
0
            continue;
326
0
        case PtCr_idiv:
327
0
            if (vsp->value.i == 0)
328
0
                return_error(gs_error_undefinedresult);
329
0
            if (vsp[-1].value.i == min_int &&
330
0
                vsp->value.i == -1)  /* anomalous boundary case, fail */
331
0
                return_error(gs_error_rangecheck);
332
0
            else
333
0
                vsp[-1].value.i /= vsp->value.i;
334
0
            --vsp; continue;
335
0
        case PtCr_ln:
336
0
            vsp->value.f = log(vsp->value.f);
337
0
            continue;
338
0
        case PtCr_log:
339
0
            vsp->value.f = log10(vsp->value.f);
340
0
            continue;
341
0
        case PtCr_mod:
342
0
            if (vsp->value.i == 0)
343
0
                return_error(gs_error_undefinedresult);
344
0
            vsp[-1].value.i %= vsp->value.i;
345
0
            --vsp; continue;
346
21
        case PtCr_mul_int: {
347
            /* We don't bother to optimize this. */
348
21
            double prod = (double)vsp[-1].value.i * vsp->value.i;
349
350
21
            if (prod < min_int || prod > max_int)
351
0
                store_float(vsp - 1, prod);
352
21
            else
353
21
                vsp[-1].value.i = (int)prod;
354
21
            --vsp; continue;
355
0
        }
356
54.5k
        case PtCr_mul:
357
54.5k
            vsp[-1].value.f *= vsp->value.f;
358
54.5k
            --vsp; continue;
359
0
        case PtCr_abs_int:
360
0
            if (vsp->value.i >= 0)
361
0
                continue;
362
            /* fallthrough */
363
0
        case PtCr_neg_int:
364
0
            if (vsp->value.i == min_int)
365
0
                store_float(vsp, (double)vsp->value.i); /* =self negated */
366
0
            else
367
0
                vsp->value.i = -vsp->value.i;
368
0
            continue;
369
0
        case PtCr_neg:
370
0
            vsp->value.f = -vsp->value.f;
371
0
            continue;
372
0
        case PtCr_not_bool:
373
0
            vsp->value.i = !vsp->value.i;
374
0
            continue;
375
0
        case PtCr_not:
376
0
            vsp->value.i = ~vsp->value.i;
377
0
            continue;
378
0
        case PtCr_or:
379
0
            vsp[-1].value.i |= vsp->value.i;
380
0
            --vsp; continue;
381
0
        case PtCr_round:
382
0
            vsp->value.f = floor(vsp->value.f + 0.5);
383
0
            continue;
384
49
        case PtCr_sin:
385
49
            vsp->value.f = gs_sin_degrees(vsp->value.f);
386
49
            continue;
387
49
        case PtCr_sqrt:
388
49
            vsp->value.f = sqrt(vsp->value.f);
389
49
            continue;
390
0
        case PtCr_sub_int: {
391
0
            int int1 = vsp[-1].value.i, int2 = vsp->value.i;
392
393
0
            if ((int1 ^ int2) < 0 && ((int1 - int2) ^ int1) >= 0)
394
0
                store_float(vsp - 1, (double)int1 - int2);
395
0
            else
396
0
                vsp[-1].value.i = int1 - int2;
397
0
            --vsp; continue;
398
0
        }
399
64.3k
        case PtCr_sub:
400
64.3k
            vsp[-1].value.f -= vsp->value.f;
401
64.3k
            --vsp; continue;
402
0
        case PtCr_truncate:
403
0
            vsp->value.f = (vsp->value.f < 0 ? ceil(vsp->value.f) :
404
0
                            floor(vsp->value.f));
405
0
            continue;
406
0
        case PtCr_xor:
407
0
            vsp[-1].value.i ^= vsp->value.i;
408
0
            --vsp; continue;
409
410
            /* Boolean operators */
411
412
0
#define DO_REL(rel, m)\
413
27.3k
  vsp[-1].value.i = vsp[-1].value.m rel vsp->value.m
414
415
0
        case PtCr_eq_int:
416
0
            DO_REL(==, i);
417
0
            goto rel;
418
1
        case PtCr_ge_int:
419
1
            DO_REL(>=, i);
420
1
            goto rel;
421
3
        case PtCr_ge:
422
3
            DO_REL(>=, f);
423
3
            goto rel;
424
36
        case PtCr_gt_int:
425
36
            DO_REL(>, i);
426
36
            goto rel;
427
12
        case PtCr_gt:
428
12
            DO_REL(>, f);
429
12
            goto rel;
430
0
        case PtCr_le_int:
431
0
            DO_REL(<=, i);
432
0
            goto rel;
433
27.2k
        case PtCr_le:
434
27.2k
            DO_REL(<=, f);
435
27.2k
            goto rel;
436
0
        case PtCr_lt_int:
437
0
            DO_REL(<, i);
438
0
            goto rel;
439
51
        case PtCr_lt:
440
51
            DO_REL(<, f);
441
51
            goto rel;
442
0
        case PtCr_ne_int:
443
0
            DO_REL(!=, i);
444
0
            goto rel;
445
0
        case PtCr_ne:
446
0
            DO_REL(!=, f);
447
0
            goto rel;
448
0
        case PtCr_eq:
449
0
            DO_REL(==, f);
450
27.3k
        rel:
451
27.3k
            vsp[-1].type = CVT_BOOL;
452
27.3k
            --vsp; continue;
453
454
0
#undef DO_REL
455
456
            /* Stack operators */
457
458
27.2k
        case PtCr_copy:
459
27.2k
            i = vsp->value.i;
460
27.2k
            n = vsp - vstack;
461
27.2k
            if (i < 0 || i >= n)
462
0
                return_error(gs_error_rangecheck);
463
27.2k
            if (i > MAX_VSTACK - (n - 1))
464
0
                return_error(gs_error_limitcheck);
465
27.2k
            memcpy(vsp, vsp - i, i * sizeof(*vsp));
466
27.2k
            vsp += i - 1;
467
27.2k
            continue;
468
54.7k
        case PtCr_dup:
469
54.7k
            vsp[1] = *vsp;
470
54.7k
            goto push;
471
78.1k
        case PtCr_exch:
472
78.1k
            vstack[MAX_VSTACK] = *vsp;
473
78.1k
            *vsp = vsp[-1];
474
78.1k
            vsp[-1] = vstack[MAX_VSTACK];
475
78.1k
            continue;
476
14
        case PtCr_index:
477
14
            i = vsp->value.i;
478
14
            if (i < 0 || i >= vsp - vstack - 1)
479
0
                return_error(gs_error_rangecheck);
480
14
            *vsp = vsp[-i - 1];
481
14
            continue;
482
84
        case PtCr_pop:
483
84
            --vsp;
484
84
            continue;
485
88
        case PtCr_roll:
486
88
            n = vsp[-1].value.i;
487
88
            i = vsp->value.i;
488
88
            if (n < 0 || n > vsp - vstack - 2)
489
0
                return_error(gs_error_rangecheck);
490
            /* We don't bother to do this efficiently. */
491
204
            for (; i > 0; i--) {
492
116
                memmove(vsp - n, vsp - (n + 1), n * sizeof(*vsp));
493
116
                vsp[-(n + 1)] = vsp[-1];
494
116
            }
495
102
            for (; i < 0; i++) {
496
14
                vsp[-1] = vsp[-(n + 1)];
497
14
                memmove(vsp - (n + 1), vsp - n, n * sizeof(*vsp));
498
14
            }
499
88
            vsp -= 2;
500
88
            continue;
501
502
            /* Constants */
503
504
92.0k
        case PtCr_byte:
505
92.0k
            vsp[1].value.i = *p++, vsp[1].type = CVT_INT;
506
92.0k
            goto push;
507
115
        case PtCr_int /* native */:
508
115
            memcpy(&vsp[1].value.i, p, sizeof(int));
509
115
            vsp[1].type = CVT_INT;
510
115
            p += sizeof(int);
511
115
            goto push;
512
27.5k
        case PtCr_float /* native */:
513
27.5k
            memcpy(&vsp[1].value.f, p, sizeof(float));
514
27.5k
            vsp[1].type = CVT_FLOAT;
515
27.5k
            p += sizeof(float);
516
27.5k
            goto push;
517
0
        case PtCr_true:
518
0
            vsp[1].value.i = true, vsp[1].type = CVT_BOOL;
519
0
            goto push;
520
0
        case PtCr_false:
521
0
            vsp[1].value.i = false, vsp[1].type = CVT_BOOL;
522
174k
        push:
523
174k
            if (vsp == &vstack[MAX_VSTACK])
524
0
                return_error(gs_error_limitcheck);
525
174k
            ++vsp;
526
174k
            continue;
527
528
            /* Special */
529
530
27.3k
        case PtCr_if:
531
27.3k
            if ((vsp--)->value.i) { /* value is true, execute body */
532
13.6k
                p += 2;
533
13.6k
                continue;
534
13.6k
            }
535
            /* falls through */
536
27.3k
        case PtCr_else:
537
27.3k
            p += 2 + (p[0] << 8) + p[1];  /* skip the past body */
538
27.3k
            continue;
539
37.1k
        case PtCr_return:
540
37.1k
            goto fin;
541
0
        case PtCr_repeat:
542
0
            repeat_nesting_level++;
543
0
            repeat_count[repeat_nesting_level] = vsp->value.i;
544
0
            repeat_proc_size[repeat_nesting_level] = 1 + (p[0] << 8) + p[1];  /* body size */
545
0
            --vsp;    /* pop the counter */
546
0
            p += 3 + (p[0] <<8) + p[1];       /* advance just past the repeat_end */
547
            /* falls through */
548
0
        case PtCr_repeat_end:
549
0
            if (repeat_nesting_level < 0)
550
0
                return_error(gs_error_rangecheck);
551
552
0
            if ((repeat_count[repeat_nesting_level])-- <= 0)
553
0
                repeat_nesting_level--;
554
0
            else
555
0
                p -= repeat_proc_size[repeat_nesting_level];
556
0
            continue;
557
678k
        }
558
678k
    }
559
37.1k
 fin:
560
37.1k
    {   /* Following Acrobat, take the desired number of parameters */
561
        /* from the top of stack and ignore the rest. Bug 702950. */
562
37.1k
        int extra_ops = vsp - vstack - pfn->params.n;
563
37.1k
        if (extra_ops < 0)
564
3
            return_error(gs_error_rangecheck);
565
74.7k
        for (i = 0; i < pfn->params.n; ++i) {
566
37.5k
            switch (vstack[i + 1 + extra_ops].type) {
567
116
            case CVT_INT:
568
116
                out[i] = (float)vstack[i + 1 + extra_ops].value.i;
569
116
                break;
570
37.4k
            case CVT_FLOAT:
571
37.4k
                out[i] = vstack[i + 1 + extra_ops].value.f;
572
37.4k
                break;
573
0
            default:
574
0
                return_error(gs_error_typecheck);
575
37.5k
            }
576
37.5k
        }
577
37.1k
    }
578
37.1k
    return 0;
579
37.1k
}
580
581
/* Test whether a PostScript Calculator function is monotonic. */
582
static int
583
fn_PtCr_is_monotonic(const gs_function_t * pfn_common,
584
                     const float *lower, const float *upper, uint *mask)
585
0
{
586
    /*
587
     * No reasonable way to tell.  Eventually we should check for
588
     * functions consisting of only stack-manipulating operations,
589
     * since these may be common for DeviceN color spaces and *are*
590
     * monotonic.
591
     */
592
0
    *mask = 0x49249249;
593
0
    return 0;
594
0
}
595
596
/* Write the function definition in symbolic form on a stream. */
597
static int
598
calc_put_ops(stream *s, const byte *ops, uint size)
599
507
{
600
507
    const byte *p;
601
602
507
    spputc(s, '{');
603
17.2k
    for (p = ops; p < ops + size; )
604
16.7k
        switch (*p++) {
605
5.89k
        case PtCr_byte:
606
5.89k
            pprintd1(s, "%d ", *p++);
607
5.89k
            break;
608
855
        case PtCr_int: {
609
855
            int i;
610
611
855
            memcpy(&i, p, sizeof(int));
612
855
            pprintd1(s, "%d ", i);
613
855
            p += sizeof(int);
614
855
            break;
615
0
        }
616
1.74k
        case PtCr_float: {
617
1.74k
            float f;
618
619
1.74k
            memcpy(&f, p, sizeof(float));
620
1.74k
            pprintg1(s, "%g ", f);
621
1.74k
            p += sizeof(float);
622
1.74k
            break;
623
0
        }
624
0
        case PtCr_true:
625
0
            stream_puts(s, "true ");
626
0
            break;
627
0
        case PtCr_false:
628
0
            stream_puts(s, "false ");
629
0
            break;
630
87
        case PtCr_if: {
631
87
            int skip = (p[0] << 8) + p[1];
632
87
            int code;
633
634
87
            code = calc_put_ops(s, p += 2, skip);
635
87
            p += skip;
636
87
            if (code < 0)
637
0
                return code;
638
87
            if (code > 0) { /* else */
639
0
                skip = (p[-2] << 8) + p[-1];
640
0
                code = calc_put_ops(s, p, skip);
641
0
                p += skip;
642
0
                if (code < 0)
643
0
                    return code;
644
0
                stream_puts(s, " ifelse ");
645
0
            } else
646
87
                stream_puts(s, " if ");
647
87
            break;
648
87
        }
649
87
        case PtCr_else:
650
0
            if (p != ops + size - 2)
651
0
                return_error(gs_error_rangecheck);
652
0
            spputc(s, '}');
653
0
            return 1;
654
        /*case PtCr_return:*/ /* not possible */
655
0
        case PtCr_repeat:   /* We shouldn't encounter this, but just in case */
656
0
        case PtCr_repeat_end:
657
0
            return_error(gs_error_rangecheck);
658
8.13k
        default: {    /* must be < PtCr_NUM_OPS */
659
8.13k
                static const char *const op_names[] = {
660
                    /* Keep this consistent with opcodes in gsfunc4.h! */
661
8.13k
                    "abs", "add", "and", "atan", "bitshift",
662
8.13k
                    "ceiling", "cos", "cvi", "cvr", "div", "exp",
663
8.13k
                    "floor", "idiv", "ln", "log", "mod", "mul",
664
8.13k
                    "neg", "not", "or", "round", "sin", "sqrt", "sub",
665
8.13k
                    "truncate", "xor",
666
8.13k
                    "eq", "ge", "gt", "le", "lt", "ne",
667
8.13k
                    "copy", "dup", "exch", "index", "pop", "roll"
668
8.13k
                };
669
670
8.13k
                pprints1(s, "%s ", op_names[p[-1]]);
671
8.13k
            }
672
16.7k
        }
673
507
    spputc(s, '}');
674
507
    return 0;
675
507
}
676
static int
677
calc_put(stream *s, const gs_function_PtCr_t *pfn)
678
420
{
679
420
    calc_put_ops(s, pfn->params.ops.data, pfn->params.ops.size - 1);
680
420
    return 0;
681
420
}
682
683
/* Access the symbolic definition as a DataSource. */
684
static int
685
calc_access(const gs_data_source_t *psrc, ulong start, uint length,
686
            byte *buf, const byte **ptr)
687
267
{
688
267
    const gs_function_PtCr_t *const pfn =
689
267
        (const gs_function_PtCr_t *)
690
267
          ((const char *)psrc - offset_of(gs_function_PtCr_t, data_source));
691
    /*
692
     * The caller wants a specific substring of the symbolic definition.
693
     * Generate the entire definition, using a SubFileDecode filter (in an
694
     * output pipeline!) to extract the substring.  This is very
695
     * inefficient, but this code is rarely used, and almost never actually
696
     * has to break up the definition into pieces to fit in the caller's
697
     * buffer.
698
     */
699
267
    stream_SFD_state st;
700
267
    stream ds, bs;
701
267
    byte dbuf[200];   /* arbitrary */
702
267
    const stream_template *const templat = &s_SFD_template;
703
704
    /* Set up the stream that writes into the buffer. */
705
267
    s_init(&bs, NULL);
706
267
    swrite_string(&bs, buf, length);
707
    /* Set up the SubFileDecode stream. */
708
267
    s_init(&ds, NULL);
709
267
    s_init_state((stream_state *)&st, templat, NULL);
710
267
    templat->set_defaults((stream_state *)&st);
711
267
    st.skip_count = start;
712
267
    s_init_filter(&ds, (stream_state *)&st, dbuf, sizeof(dbuf), &bs);
713
267
    calc_put(&ds, pfn);
714
267
    sclose(&ds);
715
267
    if (ptr)
716
267
        *ptr = buf;
717
267
    return 0;
718
267
}
719
720
/* Return PostScript Calculator function information. */
721
static void
722
fn_PtCr_get_info(const gs_function_t *pfn_common, gs_function_info_t *pfi)
723
153
{
724
153
    const gs_function_PtCr_t *const pfn =
725
153
        (const gs_function_PtCr_t *)pfn_common;
726
727
153
    gs_function_get_info_default(pfn_common, pfi);
728
153
    pfi->DataSource = &pfn->data_source;
729
153
    {
730
153
        stream s;
731
732
153
        s_init(&s, NULL);
733
153
        swrite_position_only(&s);
734
153
        calc_put(&s, pfn);
735
153
        pfi->data_size = stell(&s);
736
153
    }
737
153
}
738
739
/* Make a scaled copy of a PostScript Calculator function. */
740
static int
741
fn_PtCr_make_scaled(const gs_function_PtCr_t *pfn, gs_function_PtCr_t **ppsfn,
742
                    const gs_range_t *pranges, gs_memory_t *mem)
743
0
{
744
0
    gs_function_PtCr_t *psfn =
745
0
        gs_alloc_struct(mem, gs_function_PtCr_t, &st_function_PtCr,
746
0
                        "fn_PtCr_make_scaled");
747
    /* We are adding {<int> 1 roll <float> mul <float> add} for each output. */
748
0
    int n = pfn->params.n;
749
0
    uint opsize = pfn->params.ops.size + (9 + 2 * sizeof(float)) * n;
750
0
    byte *ops = gs_alloc_string(mem, opsize, "fn_PtCr_make_scaled(ops)");
751
0
    byte *p;
752
0
    int code, i;
753
754
0
    if (psfn == 0 || ops == 0) {
755
0
        gs_free_string(mem, ops, opsize, "fn_PtCr_make_scaled(ops)");
756
0
        gs_free_object(mem, psfn, "fn_PtCr_make_scaled");
757
0
        return_error(gs_error_VMerror);
758
0
    }
759
0
    psfn->params = pfn->params;
760
0
    psfn->params.ops.data = ops;
761
0
    psfn->params.ops.size = opsize;
762
0
    psfn->data_source = pfn->data_source;
763
0
    code = fn_common_scale((gs_function_t *)psfn, (const gs_function_t *)pfn,
764
0
                           pranges, mem);
765
0
    if (code < 0) {
766
0
        gs_function_free((gs_function_t *)psfn, true, mem);
767
0
        return code;
768
0
    }
769
0
    memcpy(ops, pfn->params.ops.data, pfn->params.ops.size - 1); /* minus return */
770
0
    p = ops + pfn->params.ops.size - 1;
771
0
    for (i = n; --i >= 0; ) {
772
0
        float base = pranges[i].rmin;
773
0
        float factor = pranges[i].rmax - base;
774
775
0
        if (factor != 1) {
776
0
            p[0] = PtCr_float; memcpy(p + 1, &factor, sizeof(float));
777
0
            p += 1 + sizeof(float);
778
0
            *p++ = PtCr_mul;
779
0
        }
780
0
        if (base != 0) {
781
0
            p[0] = PtCr_float; memcpy(p + 1, &base, sizeof(float));
782
0
            p += 1 + sizeof(float);
783
0
            *p++ = PtCr_add;
784
0
        }
785
0
        if (n != 1) {
786
0
            p[0] = PtCr_byte; p[1] = (byte)n;
787
0
            p[2] = PtCr_byte; p[3] = 1;
788
0
            p[4] = PtCr_roll;
789
0
            p += 5;
790
0
        }
791
0
    }
792
0
    *p++ = PtCr_return;
793
0
    psfn->params.ops.size = p - ops;
794
0
    psfn->params.ops.data =
795
0
        gs_resize_string(mem, ops, opsize, psfn->params.ops.size,
796
0
                         "fn_PtCr_make_scaled");
797
0
    *ppsfn = psfn;
798
0
    return 0;
799
0
}
800
801
/* Free the parameters of a PostScript Calculator function. */
802
void
803
gs_function_PtCr_free_params(gs_function_PtCr_params_t * params, gs_memory_t * mem)
804
18.6k
{
805
18.6k
    gs_free_const_string(mem, params->ops.data, params->ops.size, "ops");
806
18.6k
    params->ops.data = NULL;
807
18.6k
    params->ops.size = 0;
808
18.6k
    fn_common_free_params((gs_function_params_t *) params, mem);
809
18.6k
}
810
811
/* Serialize. */
812
static int
813
gs_function_PtCr_serialize(const gs_function_t * pfn, stream *s)
814
15.3k
{
815
15.3k
    uint n;
816
15.3k
    const gs_function_PtCr_params_t * p = (const gs_function_PtCr_params_t *)&pfn->params;
817
15.3k
    int code = fn_common_serialize(pfn, s);
818
819
15.3k
    if (code < 0)
820
0
        return code;
821
15.3k
    code = sputs(s, (const byte *)&p->ops.size, sizeof(p->ops.size), &n);
822
15.3k
    if (code < 0)
823
0
        return code;
824
15.3k
    return sputs(s, p->ops.data, p->ops.size, &n);
825
15.3k
}
826
827
/* Allocate and initialize a PostScript Calculator function. */
828
int
829
gs_function_PtCr_init(gs_function_t ** ppfn,
830
                  const gs_function_PtCr_params_t * params, gs_memory_t * mem)
831
14.9k
{
832
14.9k
    static const gs_function_head_t function_PtCr_head = {
833
14.9k
        function_type_PostScript_Calculator,
834
14.9k
        {
835
14.9k
            (fn_evaluate_proc_t) fn_PtCr_evaluate,
836
14.9k
            (fn_is_monotonic_proc_t) fn_PtCr_is_monotonic,
837
14.9k
            (fn_get_info_proc_t) fn_PtCr_get_info,
838
14.9k
            fn_common_get_params,
839
14.9k
            (fn_make_scaled_proc_t) fn_PtCr_make_scaled,
840
14.9k
            (fn_free_params_proc_t) gs_function_PtCr_free_params,
841
14.9k
            fn_common_free,
842
14.9k
            (fn_serialize_proc_t) gs_function_PtCr_serialize,
843
14.9k
        }
844
14.9k
    };
845
14.9k
    int code;
846
847
14.9k
    *ppfn = 0;      /* in case of error */
848
14.9k
    code = fn_check_mnDR((const gs_function_params_t *)params,
849
14.9k
                         params->m, params->n);
850
14.9k
    if (code < 0)
851
2
        return code;
852
14.9k
    if (params->m > MAX_VSTACK || params->n > MAX_VSTACK)
853
0
        return_error(gs_error_limitcheck);
854
    /*
855
     * Pre-validate the operation string to reduce evaluation overhead.
856
     */
857
14.9k
    {
858
14.9k
        const byte *p = params->ops.data;
859
860
686k
        for (; *p != PtCr_return; ++p)
861
671k
            switch ((gs_PtCr_opcode_t)*p) {
862
234k
            case PtCr_byte:
863
234k
                ++p; break;
864
45.8k
            case PtCr_int:
865
45.8k
                p += sizeof(int); break;
866
17.1k
            case PtCr_float:
867
17.1k
                p += sizeof(float); break;
868
0
            case PtCr_repeat:
869
3.45k
            case PtCr_if:
870
6.86k
            case PtCr_else:
871
6.86k
                p += 2;
872
6.86k
            case PtCr_repeat_end:
873
6.86k
            case PtCr_true:
874
6.86k
            case PtCr_false:
875
6.86k
                break;
876
367k
            default:
877
367k
                if (*p >= PtCr_NUM_OPS)
878
0
                    return_error(gs_error_rangecheck);
879
671k
            }
880
14.9k
        if (p != params->ops.data + params->ops.size - 1)
881
0
            return_error(gs_error_rangecheck);
882
14.9k
    }
883
14.9k
    {
884
14.9k
        gs_function_PtCr_t *pfn =
885
14.9k
            gs_alloc_struct(mem, gs_function_PtCr_t, &st_function_PtCr,
886
14.9k
                            "gs_function_PtCr_init");
887
888
14.9k
        if (pfn == 0)
889
0
            return_error(gs_error_VMerror);
890
14.9k
        pfn->params = *params;
891
        /*
892
         * We claim to have a DataSource, in order to write the function
893
         * definition in symbolic form for embedding in PDF files.
894
         * ****** THIS IS A HACK. ******
895
         */
896
14.9k
        data_source_init_string2(&pfn->data_source, NULL, 0);
897
14.9k
        pfn->data_source.access = calc_access;
898
14.9k
        pfn->head = function_PtCr_head;
899
14.9k
        *ppfn = (gs_function_t *) pfn;
900
14.9k
    }
901
0
    return 0;
902
14.9k
}