Coverage Report

Created: 2025-06-10 07:27

/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
91.1M
#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
48.9M
{
67
48.9M
    vsp->value.f = f;
68
48.9M
    vsp->type = CVT_FLOAT;
69
48.9M
}
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
9.15M
{
109
9.15M
    const gs_function_PtCr_t *pfn = (const gs_function_PtCr_t *)pfn_common;
110
9.15M
    calc_value_t vstack_buf[2 + MAX_VSTACK + 1];
111
9.15M
    calc_value_t *vstack = &vstack_buf[1];
112
9.15M
    calc_value_t *vsp = vstack + pfn->params.m;
113
9.15M
    const byte *p = pfn->params.ops.data;
114
9.15M
    int repeat_count[MAX_PSC_FUNCTION_NESTING];
115
9.15M
    int repeat_proc_size[MAX_PSC_FUNCTION_NESTING];
116
9.15M
    int repeat_nesting_level = -1;
117
9.15M
    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
9.15M
    static const struct op_defn_s {
125
9.15M
        byte opcode[16];  /* 4 * type[-1] + type[0] */
126
9.15M
    } op_defn_table[] = {
127
        /* Keep this consistent with opcodes in gsfunc4.h! */
128
129
668M
#define O4(op) op,op,op,op
130
1.47G
#define E PtCr_typecheck
131
375M
#define E4 O4(E)
132
9.15M
#define N PtCr_no_op
133
        /* 0-operand operators */
134
9.15M
#define OP_NONE(op)\
135
73.2M
  {{O4(op), O4(op), O4(op), O4(op)}}
136
        /* 1-operand operators */
137
9.15M
#define OP1(b, i, f)\
138
183M
  {{E,b,i,f, E,b,i,f, E,b,i,f, E,b,i,f}}
139
9.15M
#define OP_NUM1(i, f)\
140
73.2M
  OP1(E, i, f)
141
9.15M
#define OP_MATH1(f)\
142
45.7M
  OP1(E, PtCr_int_to_float, f)
143
9.15M
#define OP_ANY1(op)\
144
18.3M
  OP1(op, op, op)
145
        /* 2-operand operators */
146
9.15M
#define OP_NUM2(i, f)\
147
64.1M
  {{E4, E4, E,E,i,PtCr_2nd_int_to_float, E,E,PtCr_int_to_float,f}}
148
9.15M
#define OP_INT_BOOL2(i)\
149
27.4M
  {{E4, E,i,i,E, E,i,i,E, E4}}
150
9.15M
#define OP_MATH2(f)\
151
27.4M
  {{E4, E4, E,E,PtCr_int2_to_float,PtCr_2nd_int_to_float,\
152
27.4M
    E,E,PtCr_int_to_float,f}}
153
9.15M
#define OP_INT2(i)\
154
36.6M
  {{E4, E4, E,E,i,E, E4}}
155
9.15M
#define OP_REL2(i, f)\
156
18.3M
  {{E4, E,i,E,E, E,E,i,PtCr_2nd_int_to_float, E,E,PtCr_int_to_float,f}}
157
9.15M
#define OP_ANY2(op)\
158
9.15M
  {{E4, E,op,op,op, E,op,op,op, E,op,op,op}}
159
160
    /* Arithmetic operators */
161
162
9.15M
        OP_NUM1(PtCr_abs_int, PtCr_abs), /* abs */
163
9.15M
        OP_NUM2(PtCr_add_int, PtCr_add), /* add */
164
9.15M
        OP_INT_BOOL2(PtCr_and),  /* and */
165
9.15M
        OP_MATH2(PtCr_atan),  /* atan */
166
9.15M
        OP_INT2(PtCr_bitshift),  /* bitshift */
167
9.15M
        OP_NUM1(N, PtCr_ceiling),  /* ceiling */
168
9.15M
        OP_MATH1(PtCr_cos), /* cos */
169
9.15M
        OP_NUM1(N, PtCr_cvi),  /* cvi */
170
9.15M
        OP_NUM1(PtCr_int_to_float, N), /* cvr */
171
9.15M
        OP_MATH2(PtCr_div), /* div */
172
9.15M
        OP_MATH2(PtCr_exp), /* exp */
173
9.15M
        OP_NUM1(N, PtCr_floor),  /* floor */
174
9.15M
        OP_INT2(PtCr_idiv),  /* idiv */
175
9.15M
        OP_MATH1(PtCr_ln),  /* ln */
176
9.15M
        OP_MATH1(PtCr_log), /* log */
177
9.15M
        OP_INT2(PtCr_mod), /* mod */
178
9.15M
        OP_NUM2(PtCr_mul_int, PtCr_mul), /* mul */
179
9.15M
        OP_NUM1(PtCr_neg_int, PtCr_neg), /* neg */
180
9.15M
        OP1(PtCr_not, PtCr_not, E),  /* not */
181
9.15M
        OP_INT_BOOL2(PtCr_or),  /* or */
182
9.15M
        OP_NUM1(N, PtCr_round),  /* round */
183
9.15M
        OP_MATH1(PtCr_sin), /* sin */
184
9.15M
        OP_MATH1(PtCr_sqrt),  /* sqrt */
185
9.15M
        OP_NUM2(PtCr_sub_int, PtCr_sub), /* sub */
186
9.15M
        OP_NUM1(N, PtCr_truncate), /* truncate */
187
9.15M
        OP_INT_BOOL2(PtCr_xor),  /* xor */
188
189
    /* Comparison operators */
190
191
9.15M
        OP_REL2(PtCr_eq_int, PtCr_eq), /* eq */
192
9.15M
        OP_NUM2(PtCr_ge_int, PtCr_ge), /* ge */
193
9.15M
        OP_NUM2(PtCr_gt_int, PtCr_gt), /* gt */
194
9.15M
        OP_NUM2(PtCr_le_int, PtCr_le), /* le */
195
9.15M
        OP_NUM2(PtCr_lt_int, PtCr_lt), /* lt */
196
9.15M
        OP_REL2(PtCr_ne_int, PtCr_ne), /* ne */
197
198
    /* Stack operators */
199
200
9.15M
        OP1(E, PtCr_copy, E),  /* copy */
201
9.15M
        OP_ANY1(PtCr_dup), /* dup */
202
9.15M
        OP_ANY2(PtCr_exch),  /* exch */
203
9.15M
        OP1(E, PtCr_index, E), /* index */
204
9.15M
        OP_ANY1(PtCr_pop), /* pop */
205
9.15M
        OP_INT2(PtCr_roll),  /* roll */
206
207
    /* Constants */
208
209
9.15M
        OP_NONE(PtCr_byte),    /* byte */
210
9.15M
        OP_NONE(PtCr_int),   /* int */
211
9.15M
        OP_NONE(PtCr_float),   /* float */
212
9.15M
        OP_NONE(PtCr_true),    /* true */
213
9.15M
        OP_NONE(PtCr_false),   /* false */
214
215
    /* Special */
216
217
9.15M
        OP1(PtCr_if, E, E),    /* if */
218
9.15M
        OP_NONE(PtCr_else),    /* else */
219
9.15M
        OP_NONE(PtCr_return),    /* return */
220
9.15M
        OP1(E, PtCr_repeat, E),    /* repeat */
221
9.15M
        OP_NONE(PtCr_repeat_end) /* repeat_end */
222
9.15M
    };
223
224
9.15M
    memset(repeat_count, 0x00, MAX_PSC_FUNCTION_NESTING * sizeof(int));
225
9.15M
    memset(repeat_proc_size, 0x00, MAX_PSC_FUNCTION_NESTING * sizeof(int));
226
227
9.15M
    vstack[-1].type = CVT_NONE;  /* for type dispatch in empty stack case */
228
9.15M
    vstack[0].type = CVT_NONE;  /* catch underflow */
229
41.1M
    for (i = 0; i < pfn->params.m; ++i)
230
31.9M
        store_float(&vstack[i + 1], in[i]);
231
232
171M
    for (; ; ) {
233
171M
        int code, n;
234
235
171M
        switch (op_defn_table[*p++].opcode[(vsp[-1].type << 2) + vsp->type]) {
236
237
            /* Miscellaneous */
238
239
582k
        case PtCr_no_op:
240
582k
            continue;
241
29
        case PtCr_typecheck:
242
29
            return_error(gs_error_typecheck);
243
244
            /* Coerce and re-dispatch */
245
246
13.1M
        case PtCr_int_to_float:
247
13.1M
            store_float(vsp, (double)vsp->value.i);
248
13.1M
            --p; continue;
249
95.9k
        case PtCr_int2_to_float:
250
95.9k
            store_float(vsp, (double)vsp->value.i);
251
            /* fall through */
252
3.75M
        case PtCr_2nd_int_to_float:
253
3.75M
            store_float(vsp - 1, (double)vsp[-1].value.i);
254
3.75M
            --p; continue;
255
256
            /* Arithmetic operators */
257
258
3.44M
        case PtCr_abs:
259
3.44M
            vsp->value.f = fabs(vsp->value.f);
260
3.44M
            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
95.9k
        }
270
2.23M
        case PtCr_add:
271
2.23M
            vsp[-1].value.f += vsp->value.f;
272
2.23M
            --vsp; continue;
273
0
        case PtCr_and:
274
0
            vsp[-1].value.i &= vsp->value.i;
275
0
            --vsp; continue;
276
2.47M
        case PtCr_atan: {
277
2.47M
            double result;
278
279
2.47M
            code = gs_atan2_degrees(vsp[-1].value.f, vsp->value.f,
280
2.47M
                                    &result);
281
2.47M
            if (code < 0)
282
0
                return code;
283
2.47M
            vsp[-1].value.f = result;
284
2.47M
            --vsp; continue;
285
2.47M
        }
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
2.47M
        case PtCr_cos:
300
2.47M
            vsp->value.f = gs_cos_degrees(vsp->value.f);
301
2.47M
            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
2.47M
        }
313
0
        case PtCr_cvr:
314
0
            continue;  /* prepare handled it */
315
3.11M
        case PtCr_div:
316
3.11M
            if (vsp->value.f == 0)
317
0
                return_error(gs_error_undefinedresult);
318
3.11M
            vsp[-1].value.f /= vsp->value.f;
319
3.11M
            --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
2.74M
        case PtCr_mul_int: {
347
            /* We don't bother to optimize this. */
348
2.74M
            double prod = (double)vsp[-1].value.i * vsp->value.i;
349
350
2.74M
            if (prod < min_int || prod > max_int)
351
0
                store_float(vsp - 1, prod);
352
2.74M
            else
353
2.74M
                vsp[-1].value.i = (int)prod;
354
2.74M
            --vsp; continue;
355
0
        }
356
6.19M
        case PtCr_mul:
357
6.19M
            vsp[-1].value.f *= vsp->value.f;
358
6.19M
            --vsp; continue;
359
95.9k
        case PtCr_abs_int:
360
95.9k
            if (vsp->value.i >= 0)
361
95.9k
                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
3.11M
        case PtCr_sin:
385
3.11M
            vsp->value.f = gs_sin_degrees(vsp->value.f);
386
3.11M
            continue;
387
3.11M
        case PtCr_sqrt:
388
3.11M
            vsp->value.f = sqrt(vsp->value.f);
389
3.11M
            continue;
390
557k
        case PtCr_sub_int: {
391
557k
            int int1 = vsp[-1].value.i, int2 = vsp->value.i;
392
393
557k
            if ((int1 ^ int2) < 0 && ((int1 - int2) ^ int1) >= 0)
394
0
                store_float(vsp - 1, (double)int1 - int2);
395
557k
            else
396
557k
                vsp[-1].value.i = int1 - int2;
397
557k
            --vsp; continue;
398
95.9k
        }
399
10.9M
        case PtCr_sub:
400
10.9M
            vsp[-1].value.f -= vsp->value.f;
401
10.9M
            --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
3.28M
  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
17
        case PtCr_ge_int:
419
17
            DO_REL(>=, i);
420
17
            goto rel;
421
43
        case PtCr_ge:
422
43
            DO_REL(>=, f);
423
43
            goto rel;
424
336
        case PtCr_gt_int:
425
336
            DO_REL(>, i);
426
336
            goto rel;
427
112
        case PtCr_gt:
428
112
            DO_REL(>, f);
429
112
            goto rel;
430
0
        case PtCr_le_int:
431
0
            DO_REL(<=, i);
432
0
            goto rel;
433
160k
        case PtCr_le:
434
160k
            DO_REL(<=, f);
435
160k
            goto rel;
436
0
        case PtCr_lt_int:
437
0
            DO_REL(<, i);
438
0
            goto rel;
439
3.11M
        case PtCr_lt:
440
3.11M
            DO_REL(<, f);
441
3.11M
            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
3.28M
        rel:
451
3.28M
            vsp[-1].type = CVT_BOOL;
452
3.28M
            --vsp; continue;
453
454
0
#undef DO_REL
455
456
            /* Stack operators */
457
458
160k
        case PtCr_copy:
459
160k
            i = vsp->value.i;
460
160k
            n = vsp - vstack;
461
160k
            if (i < 0 || i >= n)
462
0
                return_error(gs_error_rangecheck);
463
160k
            if (i > MAX_VSTACK - (n - 1))
464
0
                return_error(gs_error_limitcheck);
465
160k
            memcpy(vsp, vsp - i, i * sizeof(*vsp));
466
160k
            vsp += i - 1;
467
160k
            continue;
468
13.0M
        case PtCr_dup:
469
13.0M
            vsp[1] = *vsp;
470
13.0M
            goto push;
471
16.0M
        case PtCr_exch:
472
16.0M
            vstack[MAX_VSTACK] = *vsp;
473
16.0M
            *vsp = vsp[-1];
474
16.0M
            vsp[-1] = vstack[MAX_VSTACK];
475
16.0M
            continue;
476
2.20M
        case PtCr_index:
477
2.20M
            i = vsp->value.i;
478
2.20M
            if (i < 0 || i >= vsp - vstack - 1)
479
0
                return_error(gs_error_rangecheck);
480
2.20M
            *vsp = vsp[-i - 1];
481
2.20M
            continue;
482
12.2M
        case PtCr_pop:
483
12.2M
            --vsp;
484
12.2M
            continue;
485
8.17M
        case PtCr_roll:
486
8.17M
            n = vsp[-1].value.i;
487
8.17M
            i = vsp->value.i;
488
8.17M
            if (n < 0 || n > vsp - vstack - 2)
489
0
                return_error(gs_error_rangecheck);
490
            /* We don't bother to do this efficiently. */
491
26.3M
            for (; i > 0; i--) {
492
18.2M
                memmove(vsp - n, vsp - (n + 1), n * sizeof(*vsp));
493
18.2M
                vsp[-(n + 1)] = vsp[-1];
494
18.2M
            }
495
9.34M
            for (; i < 0; i++) {
496
1.17M
                vsp[-1] = vsp[-(n + 1)];
497
1.17M
                memmove(vsp - (n + 1), vsp - n, n * sizeof(*vsp));
498
1.17M
            }
499
8.17M
            vsp -= 2;
500
8.17M
            continue;
501
502
            /* Constants */
503
504
32.8M
        case PtCr_byte:
505
32.8M
            vsp[1].value.i = *p++, vsp[1].type = CVT_INT;
506
32.8M
            goto push;
507
6.76M
        case PtCr_int /* native */:
508
6.76M
            memcpy(&vsp[1].value.i, p, sizeof(int));
509
6.76M
            vsp[1].type = CVT_INT;
510
6.76M
            p += sizeof(int);
511
6.76M
            goto push;
512
6.07M
        case PtCr_float /* native */:
513
6.07M
            memcpy(&vsp[1].value.f, p, sizeof(float));
514
6.07M
            vsp[1].type = CVT_FLOAT;
515
6.07M
            p += sizeof(float);
516
6.07M
            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
58.7M
        push:
523
58.7M
            if (vsp == &vstack[MAX_VSTACK])
524
1
                return_error(gs_error_limitcheck);
525
58.7M
            ++vsp;
526
58.7M
            continue;
527
528
            /* Special */
529
530
3.28M
        case PtCr_if:
531
3.28M
            if ((vsp--)->value.i) { /* value is true, execute body */
532
2.82M
                p += 2;
533
2.82M
                continue;
534
2.82M
            }
535
            /* falls through */
536
534k
        case PtCr_else:
537
534k
            p += 2 + (p[0] << 8) + p[1];  /* skip the past body */
538
534k
            continue;
539
9.15M
        case PtCr_return:
540
9.15M
            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
171M
        }
558
171M
    }
559
9.15M
 fin:
560
9.15M
    {   /* Following Acrobat, take the desired number of parameters */
561
        /* from the top of stack and ignore the rest. Bug 702950. */
562
9.15M
        int extra_ops = vsp - vstack - pfn->params.n;
563
9.15M
        if (extra_ops < 0)
564
25
            return_error(gs_error_rangecheck);
565
36.4M
        for (i = 0; i < pfn->params.n; ++i) {
566
27.2M
            switch (vstack[i + 1 + extra_ops].type) {
567
569k
            case CVT_INT:
568
569k
                out[i] = (float)vstack[i + 1 + extra_ops].value.i;
569
569k
                break;
570
26.7M
            case CVT_FLOAT:
571
26.7M
                out[i] = vstack[i + 1 + extra_ops].value.f;
572
26.7M
                break;
573
0
            default:
574
0
                return_error(gs_error_typecheck);
575
27.2M
            }
576
27.2M
        }
577
9.15M
    }
578
9.15M
    return 0;
579
9.15M
}
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
1.85k
{
600
1.85k
    const byte *p;
601
602
1.85k
    spputc(s, '{');
603
25.2k
    for (p = ops; p < ops + size; )
604
23.3k
        switch (*p++) {
605
7.64k
        case PtCr_byte:
606
7.64k
            pprintd1(s, "%d ", *p++);
607
7.64k
            break;
608
1.19k
        case PtCr_int: {
609
1.19k
            int i;
610
611
1.19k
            memcpy(&i, p, sizeof(int));
612
1.19k
            pprintd1(s, "%d ", i);
613
1.19k
            p += sizeof(int);
614
1.19k
            break;
615
0
        }
616
4.09k
        case PtCr_float: {
617
4.09k
            float f;
618
619
4.09k
            memcpy(&f, p, sizeof(float));
620
4.09k
            pprintg1(s, "%g ", f);
621
4.09k
            p += sizeof(float);
622
4.09k
            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
249
        case PtCr_if: {
631
249
            int skip = (p[0] << 8) + p[1];
632
249
            int code;
633
634
249
            code = calc_put_ops(s, p += 2, skip);
635
249
            p += skip;
636
249
            if (code < 0)
637
0
                return code;
638
249
            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
249
                stream_puts(s, " if ");
647
249
            break;
648
249
        }
649
249
        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
10.1k
        default: {    /* must be < PtCr_NUM_OPS */
659
10.1k
                static const char *const op_names[] = {
660
                    /* Keep this consistent with opcodes in gsfunc4.h! */
661
10.1k
                    "abs", "add", "and", "atan", "bitshift",
662
10.1k
                    "ceiling", "cos", "cvi", "cvr", "div", "exp",
663
10.1k
                    "floor", "idiv", "ln", "log", "mod", "mul",
664
10.1k
                    "neg", "not", "or", "round", "sin", "sqrt", "sub",
665
10.1k
                    "truncate", "xor",
666
10.1k
                    "eq", "ge", "gt", "le", "lt", "ne",
667
10.1k
                    "copy", "dup", "exch", "index", "pop", "roll"
668
10.1k
                };
669
670
10.1k
                pprints1(s, "%s ", op_names[p[-1]]);
671
10.1k
            }
672
23.3k
        }
673
1.85k
    spputc(s, '}');
674
1.85k
    return 0;
675
1.85k
}
676
static int
677
calc_put(stream *s, const gs_function_PtCr_t *pfn)
678
1.61k
{
679
1.61k
    calc_put_ops(s, pfn->params.ops.data, pfn->params.ops.size - 1);
680
1.61k
    return 0;
681
1.61k
}
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
868
{
688
868
    const gs_function_PtCr_t *const pfn =
689
868
        (const gs_function_PtCr_t *)
690
868
          ((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
868
    stream_SFD_state st;
700
868
    stream ds, bs;
701
868
    byte dbuf[200];   /* arbitrary */
702
868
    const stream_template *const templat = &s_SFD_template;
703
704
    /* Set up the stream that writes into the buffer. */
705
868
    s_init(&bs, NULL);
706
868
    swrite_string(&bs, buf, length);
707
    /* Set up the SubFileDecode stream. */
708
868
    s_init(&ds, NULL);
709
868
    s_init_state((stream_state *)&st, templat, NULL);
710
868
    templat->set_defaults((stream_state *)&st);
711
868
    st.skip_count = start;
712
868
    s_init_filter(&ds, (stream_state *)&st, dbuf, sizeof(dbuf), &bs);
713
868
    calc_put(&ds, pfn);
714
868
    sclose(&ds);
715
868
    if (ptr)
716
868
        *ptr = buf;
717
868
    return 0;
718
868
}
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
742
{
724
742
    const gs_function_PtCr_t *const pfn =
725
742
        (const gs_function_PtCr_t *)pfn_common;
726
727
742
    gs_function_get_info_default(pfn_common, pfi);
728
742
    pfi->DataSource = &pfn->data_source;
729
742
    {
730
742
        stream s;
731
732
742
        s_init(&s, NULL);
733
742
        swrite_position_only(&s);
734
742
        calc_put(&s, pfn);
735
742
        pfi->data_size = stell(&s);
736
742
    }
737
742
}
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
56.6k
{
805
56.6k
    gs_free_const_string(mem, params->ops.data, params->ops.size, "ops");
806
56.6k
    params->ops.data = NULL;
807
56.6k
    params->ops.size = 0;
808
56.6k
    fn_common_free_params((gs_function_params_t *) params, mem);
809
56.6k
}
810
811
/* Serialize. */
812
static int
813
gs_function_PtCr_serialize(const gs_function_t * pfn, stream *s)
814
19.2k
{
815
19.2k
    uint n;
816
19.2k
    const gs_function_PtCr_params_t * p = (const gs_function_PtCr_params_t *)&pfn->params;
817
19.2k
    int code = fn_common_serialize(pfn, s);
818
819
19.2k
    if (code < 0)
820
0
        return code;
821
19.2k
    code = sputs(s, (const byte *)&p->ops.size, sizeof(p->ops.size), &n);
822
19.2k
    if (code < 0)
823
0
        return code;
824
19.2k
    return sputs(s, p->ops.data, p->ops.size, &n);
825
19.2k
}
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
58.0k
{
832
58.0k
    static const gs_function_head_t function_PtCr_head = {
833
58.0k
        function_type_PostScript_Calculator,
834
58.0k
        {
835
58.0k
            (fn_evaluate_proc_t) fn_PtCr_evaluate,
836
58.0k
            (fn_is_monotonic_proc_t) fn_PtCr_is_monotonic,
837
58.0k
            (fn_get_info_proc_t) fn_PtCr_get_info,
838
58.0k
            fn_common_get_params,
839
58.0k
            (fn_make_scaled_proc_t) fn_PtCr_make_scaled,
840
58.0k
            (fn_free_params_proc_t) gs_function_PtCr_free_params,
841
58.0k
            fn_common_free,
842
58.0k
            (fn_serialize_proc_t) gs_function_PtCr_serialize,
843
58.0k
        }
844
58.0k
    };
845
58.0k
    int code;
846
847
58.0k
    *ppfn = 0;      /* in case of error */
848
58.0k
    code = fn_check_mnDR((const gs_function_params_t *)params,
849
58.0k
                         params->m, params->n);
850
58.0k
    if (code < 0)
851
15
        return code;
852
57.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
57.9k
    {
858
57.9k
        const byte *p = params->ops.data;
859
860
2.49M
        for (; *p != PtCr_return; ++p)
861
2.43M
            switch ((gs_PtCr_opcode_t)*p) {
862
741k
            case PtCr_byte:
863
741k
                ++p; break;
864
127k
            case PtCr_int:
865
127k
                p += sizeof(int); break;
866
177k
            case PtCr_float:
867
177k
                p += sizeof(float); break;
868
0
            case PtCr_repeat:
869
20.5k
            case PtCr_if:
870
40.6k
            case PtCr_else:
871
40.6k
                p += 2;
872
40.6k
            case PtCr_repeat_end:
873
40.6k
            case PtCr_true:
874
40.6k
            case PtCr_false:
875
40.6k
                break;
876
1.34M
            default:
877
1.34M
                if (*p >= PtCr_NUM_OPS)
878
0
                    return_error(gs_error_rangecheck);
879
2.43M
            }
880
57.9k
        if (p != params->ops.data + params->ops.size - 1)
881
0
            return_error(gs_error_rangecheck);
882
57.9k
    }
883
57.9k
    {
884
57.9k
        gs_function_PtCr_t *pfn =
885
57.9k
            gs_alloc_struct(mem, gs_function_PtCr_t, &st_function_PtCr,
886
57.9k
                            "gs_function_PtCr_init");
887
888
57.9k
        if (pfn == 0)
889
0
            return_error(gs_error_VMerror);
890
57.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
57.9k
        data_source_init_string2(&pfn->data_source, NULL, 0);
897
57.9k
        pfn->data_source.access = calc_access;
898
57.9k
        pfn->head = function_PtCr_head;
899
57.9k
        *ppfn = (gs_function_t *) pfn;
900
57.9k
    }
901
0
    return 0;
902
57.9k
}