Coverage Report

Created: 2026-09-14 07:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/psi/zarith.c
Line
Count
Source
1
/* Copyright (C) 2001-2023 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* Arithmetic operators */
18
#include "math_.h"
19
#include "ghost.h"
20
#include "oper.h"
21
#include "store.h"
22
#include "gsstate.h"
23
24
/*
25
 * Many of the procedures in this file are public only so they can be
26
 * called from the FunctionType 4 interpreter (zfunc4.c).
27
 */
28
29
static int mul_64_64_overflowcheck(int64_t abc, int64_t def, int64_t *res);
30
31
/* <num1> <num2> add <sum> */
32
/* We make this into a separate procedure because */
33
/* the interpreter will almost always call it directly. */
34
int
35
zop_add(i_ctx_t *i_ctx_p)
36
518M
{
37
518M
    register os_ptr op = osp;
38
518M
    float result;
39
40
518M
    check_op(2);
41
518M
    switch (r_type(op)) {
42
7
    default:
43
7
        return_op_typecheck(op);
44
49.0M
    case t_real:
45
49.0M
        switch (r_type(op - 1)) {
46
11
        default:
47
11
            return_op_typecheck(op - 1);
48
27.2M
        case t_real:
49
27.2M
            result = op[-1].value.realval + op->value.realval;
50
27.2M
#ifdef HAVE_ISINF
51
27.2M
            if (isinf(result))
52
3
                return_error(gs_error_undefinedresult);
53
27.2M
#endif
54
27.2M
#ifdef HAVE_ISNAN
55
27.2M
            if (isnan(result))
56
0
                return_error(gs_error_undefinedresult);
57
27.2M
#endif
58
27.2M
            op[-1].value.realval = result;
59
27.2M
            break;
60
21.7M
        case t_integer:
61
21.7M
            make_real(op - 1, (double)op[-1].value.intval + op->value.realval);
62
49.0M
        }
63
49.0M
        break;
64
469M
    case t_integer:
65
469M
        switch (r_type(op - 1)) {
66
7
        default:
67
7
            return_op_typecheck(op - 1);
68
53.5M
        case t_real:
69
53.5M
            result = op[-1].value.realval + (double)op->value.intval;
70
53.5M
#ifdef HAVE_ISINF
71
53.5M
            if (isinf(result))
72
2
                return_error(gs_error_undefinedresult);
73
53.5M
#endif
74
53.5M
#ifdef HAVE_ISNAN
75
53.5M
            if (isnan(result))
76
0
                return_error(gs_error_undefinedresult);
77
53.5M
#endif
78
53.5M
            op[-1].value.realval = result;
79
53.5M
            break;
80
415M
        case t_integer: {
81
415M
            if (sizeof(ps_int) != 4 && gs_currentcpsimode(imemory)) {
82
0
                ps_int32 int1 = (ps_int32)op[-1].value.intval;
83
0
                ps_int32 int2 = (ps_int32)op->value.intval;
84
85
0
                if (((int1 += int2) ^ int2) < 0 &&
86
0
                    ((int1 - int2) ^ int2) >= 0
87
0
                    ) {                     /* Overflow, convert to real */
88
0
                    make_real(op - 1, (double)(int1 - int2) + int2);
89
0
                }
90
0
                else {
91
0
                    op[-1].value.intval = (ps_int)int1;
92
0
                }
93
0
            }
94
415M
            else {
95
415M
                ps_int int2 = op->value.intval;
96
97
415M
                if (((op[-1].value.intval += int2) ^ int2) < 0 &&
98
2.21k
                    ((op[-1].value.intval - int2) ^ int2) >= 0
99
415M
                    ) {                     /* Overflow, convert to real */
100
344
                    make_real(op - 1, (double)(op[-1].value.intval - int2) + int2);
101
344
                }
102
415M
            }
103
415M
        }
104
469M
        }
105
518M
    }
106
518M
    return 0;
107
518M
}
108
int
109
zadd(i_ctx_t *i_ctx_p)
110
0
{
111
0
    int code = zop_add(i_ctx_p);
112
113
0
    if (code == 0) {
114
0
        pop(1);
115
0
    }
116
0
    return code;
117
0
}
118
119
/* <num1> <num2> div <real_quotient> */
120
int
121
zdiv(i_ctx_t *i_ctx_p)
122
33.1M
{
123
33.1M
    os_ptr op = osp;
124
33.1M
    os_ptr op1 = op - 1;
125
33.1M
    float result;
126
127
33.1M
    check_op(2);
128
    /* We can't use the non_int_cases macro, */
129
    /* because we have to check explicitly for op == 0. */
130
33.1M
    switch (r_type(op)) {
131
8
        default:
132
8
            return_op_typecheck(op);
133
1.84M
        case t_real:
134
1.84M
            if (op->value.realval == 0)
135
7
                return_error(gs_error_undefinedresult);
136
1.84M
            switch (r_type(op1)) {
137
6
                default:
138
6
                    return_op_typecheck(op1);
139
1.77M
                case t_real:
140
1.77M
                    result = op1->value.realval / op->value.realval;
141
1.77M
#ifdef HAVE_ISINF
142
1.77M
                    if (isinf(result))
143
3
                        return_error(gs_error_undefinedresult);
144
1.77M
#endif
145
1.77M
#ifdef HAVE_ISNAN
146
1.77M
                    if (isnan(result))
147
1
                        return_error(gs_error_undefinedresult);
148
1.77M
#endif
149
1.77M
                    op1->value.realval = result;
150
1.77M
                    break;
151
65.3k
                case t_integer:
152
65.3k
                    result = (double)op1->value.intval / op->value.realval;
153
65.3k
#ifdef HAVE_ISINF
154
65.3k
                    if (isinf(result))
155
0
                        return_error(gs_error_undefinedresult);
156
65.3k
#endif
157
65.3k
#ifdef HAVE_ISNAN
158
65.3k
                    if (isnan(result))
159
0
                        return_error(gs_error_undefinedresult);
160
65.3k
#endif
161
1.84M
                    make_real(op1, result);
162
1.84M
            }
163
1.84M
            break;
164
31.3M
        case t_integer:
165
31.3M
            if (op->value.intval == 0)
166
8
                return_error(gs_error_undefinedresult);
167
31.3M
            switch (r_type(op1)) {
168
6
                default:
169
6
                    return_op_typecheck(op1);
170
24.4M
                case t_real:
171
24.4M
                    result = op1->value.realval / (double)op->value.intval;
172
24.4M
#ifdef HAVE_ISINF
173
24.4M
                    if (isinf(result))
174
0
                        return_error(gs_error_undefinedresult);
175
24.4M
#endif
176
24.4M
#ifdef HAVE_ISNAN
177
24.4M
                    if (isnan(result))
178
0
                        return_error(gs_error_undefinedresult);
179
24.4M
#endif
180
24.4M
                    op1->value.realval = result;
181
24.4M
                    break;
182
6.85M
                case t_integer:
183
6.85M
                    result = (double)op1->value.intval / (double)op->value.intval;
184
6.85M
#ifdef HAVE_ISINF
185
6.85M
                    if (isinf(result))
186
0
                        return_error(gs_error_undefinedresult);
187
6.85M
#endif
188
6.85M
#ifdef HAVE_ISNAN
189
6.85M
                    if (isnan(result))
190
0
                        return_error(gs_error_undefinedresult);
191
6.85M
#endif
192
31.3M
                    make_real(op1, result);
193
31.3M
            }
194
33.1M
    }
195
33.1M
    pop(1);
196
33.1M
    return 0;
197
33.1M
}
198
199
/*
200
To detect 64bit x 64bit multiplication overflowing, consider
201
breaking the numbers down into 32bit chunks.
202
203
  abc = (a<<64) + (b<<32) + c
204
      (where a is 0 or -1, and b and c are 32bit unsigned.
205
206
Similarly:
207
208
  def = (d<<64) + (b<<32) + f
209
210
Then:
211
212
  abc.def = ((a<<64) + (b<<32) + c) * ((d<<64) + (e<<32) + f)
213
          = (a<<64).def + (d<<64).abc + (b<<32).(e<<32) +
214
            (b<<32).f + (e<<32).c + cf
215
          = (a.def + d.abc + b.e)<<64 + (b.f + e.c)<<32 + cf
216
217
*/
218
219
static int mul_64_64_overflowcheck(int64_t abc, int64_t def, int64_t *res)
220
14.8M
{
221
14.8M
  uint32_t b = (abc>>32);
222
14.8M
  uint32_t c = (uint32_t)abc;
223
14.8M
  uint32_t e = (def>>32);
224
14.8M
  uint32_t f = (uint32_t)def;
225
14.8M
  uint64_t low, mid, high, bf, ec;
226
227
  /* Low contribution */
228
14.8M
  low = (uint64_t)c * (uint64_t)f;
229
  /* Mid contributions */
230
14.8M
  bf = (uint64_t)b * (uint64_t)f;
231
14.8M
  ec = (uint64_t)e * (uint64_t)c;
232
  /* Top contribution */
233
14.8M
  high = (uint64_t)b * (uint64_t)e;
234
14.8M
  if (abc < 0)
235
327
      high -= def;
236
14.8M
  if (def < 0)
237
35
      high -= abc;
238
  /* How do we check for carries from 64bit unsigned adds?
239
   *  x + y >= (1<<64) == x >= (1<<64) - y
240
   *                   == x >  (1<<64) - y - 1
241
   * if we consider just 64bits, this is:
242
   * x > NOT y
243
   */
244
14.8M
  if (bf > ~ec)
245
10
      high += ((uint64_t)1)<<32;
246
14.8M
  mid = bf + ec;
247
14.8M
  if (low > ~(mid<<32))
248
10
      high += 1;
249
14.8M
  high += (mid>>32);
250
14.8M
  low += (mid<<32);
251
252
14.8M
  *res = low;
253
254
14.8M
  return (int64_t)low < 0 ? high != -1 : high != 0;
255
14.8M
}
256
257
/* <num1> <num2> mul <product> */
258
int
259
zmul(i_ctx_t *i_ctx_p)
260
119M
{
261
119M
    os_ptr op = osp;
262
119M
    float result;
263
264
119M
    switch (r_type(op)) {
265
15
    default:
266
15
        return_op_typecheck(op);
267
59.3M
    case t_real:
268
59.3M
        switch (r_type(op - 1)) {
269
11
        default:
270
11
            return_op_typecheck(op - 1);
271
58.5M
        case t_real:
272
58.5M
            result = op[-1].value.realval * op->value.realval;
273
58.5M
#ifdef HAVE_ISINF
274
58.5M
            if (isinf(result))
275
22
                return_error(gs_error_undefinedresult);
276
58.5M
#endif
277
58.5M
#ifdef HAVE_ISNAN
278
58.5M
            if (isnan(result))
279
0
                return_error(gs_error_undefinedresult);
280
58.5M
#endif
281
58.5M
            op[-1].value.realval = result;
282
58.5M
            break;
283
806k
        case t_integer:
284
806k
            result = (double)op[-1].value.intval * op->value.realval;
285
806k
            make_real(op - 1, result);
286
59.3M
        }
287
59.3M
        break;
288
60.4M
    case t_integer:
289
60.4M
        switch (r_type(op - 1)) {
290
8
        default:
291
8
            return_op_typecheck(op - 1);
292
45.5M
        case t_real:
293
45.5M
            result = op[-1].value.realval * (double)op->value.intval;
294
45.5M
#ifdef HAVE_ISINF
295
45.5M
            if (isinf(result))
296
3
                return_error(gs_error_undefinedresult);
297
45.5M
#endif
298
45.5M
#ifdef HAVE_ISNAN
299
45.5M
            if (isnan(result))
300
0
                return_error(gs_error_undefinedresult);
301
45.5M
#endif
302
45.5M
            op[-1].value.realval = result;
303
45.5M
            break;
304
14.8M
        case t_integer: {
305
14.8M
            if (sizeof(ps_int) != 4 && gs_currentcpsimode(imemory)) {
306
0
                double ab = (double)op[-1].value.intval * op->value.intval;
307
0
                if (ab > (double)MAX_PS_INT32)       /* (double)0x7fffffff */
308
0
                    make_real(op - 1, ab);
309
0
                else if (ab < (double)MIN_PS_INT32) /* (double)(int)0x80000000 */
310
0
                    make_real(op - 1, ab);
311
0
                else
312
0
                    op[-1].value.intval = (ps_int)ab;
313
0
            }
314
14.8M
            else {
315
14.8M
                int64_t result;
316
14.8M
                if (mul_64_64_overflowcheck(op[-1].value.intval, op->value.intval, &result)) {
317
1
                    double ab = (double)op[-1].value.intval * op->value.intval;
318
1
                    make_real(op - 1, ab);
319
14.8M
                } else {
320
14.8M
                    op[-1].value.intval = result;
321
14.8M
                }
322
14.8M
            }
323
14.8M
        }
324
60.4M
        }
325
119M
    }
326
119M
    pop(1);
327
119M
    return 0;
328
119M
}
329
330
/* <num1> <num2> sub <difference> */
331
/* We make this into a separate procedure because */
332
/* the interpreter will almost always call it directly. */
333
int
334
zop_sub(i_ctx_t *i_ctx_p)
335
88.0M
{
336
88.0M
    register os_ptr op = osp;
337
338
88.0M
    check_op(2);
339
88.0M
    switch (r_type(op)) {
340
73
    default:
341
73
        return_op_typecheck(op);
342
24.0M
    case t_real:
343
24.0M
        switch (r_type(op - 1)) {
344
13
        default:
345
13
            return_op_typecheck(op - 1);
346
329k
        case t_real:
347
329k
            op[-1].value.realval -= op->value.realval;
348
329k
            break;
349
23.7M
        case t_integer:
350
23.7M
            make_real(op - 1, (double)op[-1].value.intval - op->value.realval);
351
24.0M
        }
352
24.0M
        break;
353
63.9M
    case t_integer:
354
63.9M
        switch (r_type(op - 1)) {
355
6
        default:
356
6
            return_op_typecheck(op - 1);
357
60.6k
        case t_real:
358
60.6k
            op[-1].value.realval -= (double)op->value.intval;
359
60.6k
            break;
360
63.9M
        case t_integer: {
361
63.9M
            if (sizeof(ps_int) != 4 && gs_currentcpsimode(imemory)) {
362
0
                ps_int32 int1 = (ps_int)op[-1].value.intval;
363
0
                ps_int32 int2 = (ps_int)op->value.intval;
364
0
                ps_int32 int3;
365
366
0
                if ((int1 ^ (int3 = int1 - int2)) < 0 &&
367
0
                    (int1 ^ int2) < 0
368
0
                    ) {                     /* Overflow, convert to real */
369
0
                    make_real(op - 1, (float)int1 - op->value.intval);
370
0
                }
371
0
                else {
372
0
                    op[-1].value.intval = (ps_int)int3;
373
0
                }
374
0
            }
375
63.9M
            else {
376
63.9M
                ps_int int1 = op[-1].value.intval;
377
378
63.9M
                if ((int1 ^ (op[-1].value.intval = int1 - op->value.intval)) < 0 &&
379
78.7k
                    (int1 ^ op->value.intval) < 0
380
63.9M
                    ) {                     /* Overflow, convert to real */
381
0
                    make_real(op - 1, (float)int1 - op->value.intval);
382
0
                }
383
63.9M
            }
384
63.9M
        }
385
63.9M
        }
386
88.0M
    }
387
88.0M
    return 0;
388
88.0M
}
389
int
390
zsub(i_ctx_t *i_ctx_p)
391
0
{
392
0
    int code = zop_sub(i_ctx_p);
393
394
0
    if (code == 0) {
395
0
        pop(1);
396
0
    }
397
0
    return code;
398
0
}
399
400
/* <num1> <num2> idiv <int_quotient> */
401
int
402
zidiv(i_ctx_t *i_ctx_p)
403
38.3M
{
404
38.3M
    os_ptr op = osp;
405
406
38.3M
    check_op(2);
407
38.3M
    check_type(*op, t_integer);
408
38.3M
    check_type(op[-1], t_integer);
409
38.3M
    if (sizeof(ps_int) && gs_currentcpsimode(imemory)) {
410
0
        int tmpval;
411
0
        if ((op->value.intval == 0) || (op[-1].value.intval == (ps_int)MIN_PS_INT32 && op->value.intval == -1)) {
412
            /* Anomalous boundary case: -MININT / -1, fail. */
413
0
            return_error(gs_error_undefinedresult);
414
0
        }
415
0
        tmpval = (int)op[-1].value.intval / op->value.intval;
416
0
        op[-1].value.intval = (int64_t)tmpval;
417
0
    }
418
38.3M
    else {
419
38.3M
        if ((op->value.intval == 0) || (op[-1].value.intval == MIN_PS_INT && op->value.intval == -1)) {
420
            /* Anomalous boundary case: -MININT / -1, fail. */
421
3
            return_error(gs_error_undefinedresult);
422
3
        }
423
38.3M
        op[-1].value.intval /= op->value.intval;
424
38.3M
    }
425
38.3M
    pop(1);
426
38.3M
    return 0;
427
38.3M
}
428
429
/* <int1> <int2> mod <remainder> */
430
int
431
zmod(i_ctx_t *i_ctx_p)
432
7.10M
{
433
7.10M
    os_ptr op = osp;
434
435
7.10M
    check_op(2);
436
7.10M
    check_type(*op, t_integer);
437
7.10M
    check_type(op[-1], t_integer);
438
7.10M
    if (op->value.intval == 0 || op[-1].value.intval == MIN_PS_INT)
439
7
        return_error(gs_error_undefinedresult);
440
7.10M
    op[-1].value.intval %= op->value.intval;
441
7.10M
    pop(1);
442
7.10M
    return 0;
443
7.10M
}
444
445
/* <num1> neg <num2> */
446
int
447
zneg(i_ctx_t *i_ctx_p)
448
5.13M
{
449
5.13M
    os_ptr op = osp;
450
451
5.13M
    check_op(1);
452
5.13M
    switch (r_type(op)) {
453
6
        default:
454
6
            return_op_typecheck(op);
455
2.11M
        case t_real:
456
2.11M
            op->value.realval = -op->value.realval;
457
2.11M
            break;
458
3.01M
        case t_integer:
459
3.01M
            if (sizeof(ps_int) != 32 && gs_currentcpsimode(imemory)) {
460
0
                if (((unsigned int)op->value.intval) == MIN_PS_INT32)
461
0
                    make_real(op, -(float)(ps_uint32)MIN_PS_INT32);
462
0
                else
463
0
                    op->value.intval = -op->value.intval;
464
0
            }
465
3.01M
            else {
466
3.01M
                if (op->value.intval == MIN_PS_INT)
467
3.01M
                    make_real(op, -(float)MIN_PS_INT);
468
3.01M
                else
469
3.01M
                    op->value.intval = -op->value.intval;
470
3.01M
            }
471
5.13M
    }
472
5.13M
    return 0;
473
5.13M
}
474
475
/* <num1> abs <num2> */
476
int
477
zabs(i_ctx_t *i_ctx_p)
478
9.97M
{
479
9.97M
    os_ptr op = osp;
480
481
9.97M
    check_op(1);
482
9.97M
    switch (r_type(op)) {
483
58
        default:
484
58
            return_op_typecheck(op);
485
3.00M
        case t_real:
486
3.00M
            if (op->value.realval >= 0)
487
1.66M
                return 0;
488
1.34M
            break;
489
6.96M
        case t_integer:
490
6.96M
            if (op->value.intval >= 0)
491
6.96M
                return 0;
492
95
            break;
493
9.97M
    }
494
1.34M
    return zneg(i_ctx_p);
495
9.97M
}
496
497
/* <num1> ceiling <num2> */
498
int
499
zceiling(i_ctx_t *i_ctx_p)
500
181
{
501
181
    os_ptr op = osp;
502
503
181
    check_op(1);
504
172
    switch (r_type(op)) {
505
9
        default:
506
9
            return_op_typecheck(op);
507
98
        case t_real:
508
98
            op->value.realval = ceil(op->value.realval);
509
163
        case t_integer:;
510
172
    }
511
163
    return 0;
512
172
}
513
514
/* <num1> floor <num2> */
515
int
516
zfloor(i_ctx_t *i_ctx_p)
517
228
{
518
228
    os_ptr op = osp;
519
520
228
    check_op(1);
521
220
    switch (r_type(op)) {
522
5
        default:
523
5
            return_op_typecheck(op);
524
103
        case t_real:
525
103
            op->value.realval = floor(op->value.realval);
526
215
        case t_integer:;
527
220
    }
528
215
    return 0;
529
220
}
530
531
/* <num1> round <num2> */
532
int
533
zround(i_ctx_t *i_ctx_p)
534
3.93k
{
535
3.93k
    os_ptr op = osp;
536
537
3.93k
    check_op(1);
538
3.92k
    switch (r_type(op)) {
539
6
        default:
540
6
            return_op_typecheck(op);
541
721
        case t_real:
542
721
            op->value.realval = floor(op->value.realval + 0.5);
543
3.91k
        case t_integer:;
544
3.92k
    }
545
3.91k
    return 0;
546
3.92k
}
547
548
/* <num1> truncate <num2> */
549
int
550
ztruncate(i_ctx_t *i_ctx_p)
551
32.3k
{
552
32.3k
    os_ptr op = osp;
553
554
32.3k
    check_op(1);
555
32.3k
    switch (r_type(op)) {
556
7
        default:
557
7
            return_op_typecheck(op);
558
1.40k
        case t_real:
559
1.40k
            op->value.realval =
560
1.40k
                (op->value.realval < 0.0 ?
561
13
                 ceil(op->value.realval) :
562
1.40k
                 floor(op->value.realval));
563
32.3k
        case t_integer:;
564
32.3k
    }
565
32.3k
    return 0;
566
32.3k
}
567
568
/* Non-standard operators */
569
570
/* <int1> <int2> .bitadd <sum> */
571
static int
572
zbitadd(i_ctx_t *i_ctx_p)
573
0
{
574
0
    os_ptr op = osp;
575
576
0
    check_op(2);
577
0
    check_type(*op, t_integer);
578
0
    check_type(op[-1], t_integer);
579
0
    op[-1].value.intval += op->value.intval;
580
0
    pop(1);
581
0
    return 0;
582
0
}
583
584
/* ------ Initialization table ------ */
585
586
const op_def zarith_op_defs[] =
587
{
588
    {"1abs", zabs},
589
    {"2add", zadd},
590
    {"2.bitadd", zbitadd},
591
    {"1ceiling", zceiling},
592
    {"2div", zdiv},
593
    {"2idiv", zidiv},
594
    {"1floor", zfloor},
595
    {"2mod", zmod},
596
    {"2mul", zmul},
597
    {"1neg", zneg},
598
    {"1round", zround},
599
    {"2sub", zsub},
600
    {"1truncate", ztruncate},
601
    op_def_end(0)
602
};