Coverage Report

Created: 2026-02-14 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/psi/iscannum.c
Line
Count
Source
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
/* Number scanner for Ghostscript interpreter */
18
#include "math_.h"
19
#include "ghost.h"
20
#include "ierrors.h"
21
#include "scommon.h"
22
#include "iscan.h"
23
#include "iscannum.h"   /* defines interface */
24
#include "scanchar.h"
25
#include "store.h"
26
27
/*
28
 * Warning: this file has a "spaghetti" control structure.  But since this
29
 * code accounts for over 10% of the execution time of some PostScript
30
 * files, this is one of the few places we feel this is justified.
31
 */
32
33
/*
34
 * Scan a number.  If the number consumes the entire string, return 0;
35
 * if not, set *psp to the first character beyond the number and return 1.
36
 */
37
int
38
scan_number(const byte * str, const byte * end, int sign,
39
            ref * pref, const byte ** psp, int scanner_options)
40
5.10G
{
41
5.10G
    const byte *sp = str;
42
5.10G
#define GET_NEXT(cvar, sp, end_action)\
43
20.7G
  if (sp >= end) { end_action; } else cvar = *sp++
44
45
    /*
46
     * Powers of 10 up to 6 can be represented accurately as
47
     * a single-precision float.
48
     */
49
5.10G
#define NUM_POWERS_10 6
50
5.10G
    static const float powers_10[NUM_POWERS_10 + 1] = {
51
5.10G
        1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6
52
5.10G
    };
53
5.10G
    static const double neg_powers_10[NUM_POWERS_10 + 1] = {
54
5.10G
        1e0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6
55
5.10G
    };
56
57
5.10G
    ps_int ival;
58
5.10G
    double dval;
59
5.10G
    int exp10;
60
5.10G
    int code = 0;
61
5.10G
    int c, d;
62
5.10G
    ps_int max_ps_int_scan, min_ps_int_scan;
63
5.10G
    const byte *const decoder = scan_char_decoder;
64
5.10G
#define IS_DIGIT(d, c)\
65
13.7G
  ((d = decoder[c]) < 10)
66
5.10G
#define WOULD_OVERFLOW(val, d, maxv)\
67
5.10G
  (val >= maxv / 10 && (val > maxv / 10 || d > (int64_t)(maxv % 10)))
68
69
5.10G
    GET_NEXT(c, sp, return_error(gs_error_syntaxerror));
70
5.10G
    if (!IS_DIGIT(d, c)) {
71
1.00G
        if (c != '.')
72
624k
            return_error(gs_error_syntaxerror);
73
        /* Might be a number starting with '.'. */
74
1.00G
        GET_NEXT(c, sp, return_error(gs_error_syntaxerror));
75
1.00G
        if (!IS_DIGIT(d, c))
76
1.00G
            return_error(gs_error_syntaxerror);
77
91.1k
        ival = 0;
78
91.1k
        goto i2r;
79
1.00G
    }
80
    /* Accumulate an integer in ival. */
81
    /* Do up to 4 digits without a loop, */
82
    /* since we know this can't overflow and since */
83
    /* most numbers have 4 (integer) digits or fewer. */
84
4.10G
    ival = d;
85
4.10G
    if (end - sp >= 3) { /* just check once */
86
4.00G
        if (!IS_DIGIT(d, (c = *sp))) {
87
821M
            sp++;
88
821M
            goto ind;
89
821M
        }
90
3.18G
        ival = ival * 10 + d;
91
3.18G
        if (!IS_DIGIT(d, (c = sp[1]))) {
92
3.07G
            sp += 2;
93
3.07G
            goto ind;
94
3.07G
        }
95
107M
        ival = ival * 10 + d;
96
107M
        sp += 3;
97
107M
        if (!IS_DIGIT(d, (c = sp[-1])))
98
61.8M
            goto ind;
99
45.4M
        ival = ival * 10 + d;
100
45.4M
    }
101
102
137M
    max_ps_int_scan = scanner_options & SCAN_CPSI_MODE ? MAX_PS_INT32 : MAX_PS_INT;
103
137M
    min_ps_int_scan = scanner_options & SCAN_CPSI_MODE ? MIN_PS_INT32 : MIN_PS_INT;
104
105
208M
    for (;; ival = ival * 10 + d) {
106
208M
        GET_NEXT(c, sp, goto iret);
107
111M
        if (!IS_DIGIT(d, c))
108
39.6M
            break;
109
71.4M
        if (WOULD_OVERFLOW(((ps_uint)ival), d, max_ps_int_scan)) {
110
66.8k
            if (ival == max_ps_int_scan / 10 && d == (max_ps_int_scan % 10) + 1 && sign < 0) {
111
6.29k
                GET_NEXT(c, sp, c = EOFC);
112
6.29k
                dval = -(double)min_ps_int_scan;
113
6.29k
                if (c == 'e' || c == 'E') {
114
22
                    exp10 = 0;
115
22
                    goto fs;
116
6.27k
                } else if (c == '.') {
117
75
                    GET_NEXT(c, sp, c = EOFC);
118
75
                    exp10 = 0;
119
75
                    goto fd;
120
6.19k
                } else if (!IS_DIGIT(d, c)) {
121
6.16k
                    ival = min_ps_int_scan;
122
6.16k
                    break;
123
6.16k
                }
124
6.29k
            } else
125
60.5k
                dval = (double)ival;
126
60.5k
            goto l2d;
127
66.8k
        }
128
71.4M
    }
129
4.00G
  ind:        /* We saw a non-digit while accumulating an integer in ival. */
130
4.00G
    switch (c) {
131
27.4M
        case '.':
132
27.4M
            GET_NEXT(c, sp, c = EOFC);
133
27.4M
            goto i2r;
134
959M
        default:
135
959M
            *psp = sp;
136
959M
            code = 1;
137
959M
            break;
138
177
        case EOFC:
139
177
            break;
140
353k
        case 'e':
141
367k
        case 'E':
142
367k
            if (sign < 0)
143
3.98k
                ival = -ival;
144
367k
            dval = (double)ival;
145
367k
            exp10 = 0;
146
367k
            goto fe;
147
3.01G
        case '#':
148
3.01G
            {
149
3.01G
                const int radix = ival;
150
3.01G
                ps_int uval = 0, imax;
151
152
3.01G
                if (sign || radix < min_radix || radix > max_radix)
153
24.9k
                    return_error(gs_error_syntaxerror);
154
                /* Avoid multiplies for power-of-2 radix. */
155
3.01G
                if (!(radix & (radix - 1))) {
156
3.01G
                    int shift;
157
158
3.01G
                    switch (radix) {
159
7.35k
                        case 2:
160
7.35k
                            shift = 1, imax = MAX_PS_UINT >> 1;
161
7.35k
                            break;
162
17.2k
                        case 4:
163
17.2k
                            shift = 2, imax = MAX_PS_UINT >> 2;
164
17.2k
                            break;
165
827
                        case 8:
166
827
                            shift = 3, imax = MAX_PS_UINT >> 3;
167
827
                            break;
168
3.01G
                        case 16:
169
3.01G
                            shift = 4, imax = MAX_PS_UINT >> 4;
170
3.01G
                            break;
171
1.01k
                        case 32:
172
1.01k
                            shift = 5, imax = MAX_PS_UINT >> 5;
173
1.01k
                            break;
174
0
                        default:  /* can't happen */
175
0
                            return_error(gs_error_rangecheck);
176
3.01G
                    }
177
14.3G
                    for (;; uval = (uval << shift) + d) {
178
14.3G
                        GET_NEXT(c, sp, break);
179
12.8G
                        d = decoder[c];
180
12.8G
                        if (d >= radix) {
181
1.55G
                            *psp = sp;
182
1.55G
                            code = 1;
183
1.55G
                            break;
184
1.55G
                        }
185
11.3G
                        if (uval > imax)
186
49
                            return_error(gs_error_limitcheck);
187
11.3G
                    }
188
3.01G
                } else {
189
9.03k
                    ps_int irem = MAX_PS_UINT % radix;
190
191
9.03k
                    imax = MAX_PS_UINT / radix;
192
20.7k
                    for (;; uval = uval * radix + d) {
193
20.7k
                        GET_NEXT(c, sp, break);
194
17.1k
                        d = decoder[c];
195
17.1k
                        if (d >= radix) {
196
5.27k
                            *psp = sp;
197
5.27k
                            code = 1;
198
5.27k
                            break;
199
5.27k
                        }
200
11.8k
                        if (uval >= imax &&
201
123
                            (uval > imax || d > irem)
202
11.8k
                            )
203
123
                            return_error(gs_error_limitcheck);
204
11.8k
                    }
205
9.03k
                }
206
3.01G
                if (scanner_options & SCAN_CPSI_MODE) {
207
0
                    ps_uint32 int1 = 0;
208
0
                    int1 |= (uval & 0xffffffff);
209
0
                    make_int(pref, (ps_int)((ps_int32)int1));
210
0
                }
211
3.01G
                else
212
3.01G
                    make_int(pref, uval);
213
214
3.01G
                return code;
215
3.01G
            }
216
4.00G
    }
217
1.05G
iret:
218
1.05G
    if (scanner_options & SCAN_CPSI_MODE) {
219
0
        make_int(pref, (sign < 0 ? (ps_int32)-ival : (ps_int32)ival));
220
0
    }
221
1.05G
    else {
222
1.05G
        make_int(pref, (sign < 0 ? (ps_int)-ival : (ps_int)ival));
223
1.05G
    }
224
1.05G
    return code;
225
226
    /* Accumulate a double in dval. */
227
60.5k
l2d:
228
60.5k
    exp10 = 0;
229
511k
    for (;;) {
230
511k
        dval = dval * 10 + d;
231
511k
        GET_NEXT(c, sp, c = EOFC);
232
511k
        if (!IS_DIGIT(d, c))
233
60.5k
            break;
234
511k
    }
235
60.5k
    switch (c) {
236
2.54k
        case '.':
237
2.54k
            GET_NEXT(c, sp, c = EOFC);
238
2.54k
            exp10 = 0;
239
2.54k
            goto fd;
240
44.8k
        default:
241
44.8k
            *psp = sp;
242
44.8k
            code = 1;
243
            /* falls through */
244
52.3k
        case EOFC:
245
52.3k
            if (sign < 0)
246
9.50k
                dval = -dval;
247
52.3k
            goto rret;
248
1.81k
        case 'e':
249
2.94k
        case 'E':
250
2.94k
            exp10 = 0;
251
2.94k
            goto fs;
252
2.65k
        case '#':
253
2.65k
            return_error(gs_error_syntaxerror);
254
60.5k
    }
255
256
    /* We saw a '.' while accumulating an integer in ival. */
257
27.4M
i2r:
258
27.4M
    exp10 = 0;
259
105M
    while (IS_DIGIT(d, c) || c == '-') {
260
        /*
261
         * PostScript gives an error on numbers with a '-' following a '.'
262
         * Adobe Acrobat Reader (PDF) apparently doesn't treat this as an
263
         * error. Experiments show that the numbers following the '-' are
264
         * ignored, so we swallow the fractional part. SCAN_PDF_INV_NUM
265
         *  enables this compatibility kloodge.
266
         */
267
78.0M
        if (c == '-') {
268
643
            if ((SCAN_PDF_INV_NUM & scanner_options) == 0)
269
643
                break;
270
0
            do {
271
0
                GET_NEXT(c, sp, c = EOFC);
272
0
            } while (IS_DIGIT(d, c));
273
0
            break;
274
643
        }
275
78.0M
        if (WOULD_OVERFLOW(ival, d, max_int)) {
276
67.8k
            dval = (double)ival;
277
67.8k
            goto fd;
278
67.8k
        }
279
77.9M
        ival = ival * 10 + d;
280
77.9M
        exp10--;
281
77.9M
        GET_NEXT(c, sp, c = EOFC);
282
77.9M
    }
283
27.4M
    if (sign < 0)
284
2.19M
        ival = -ival;
285
    /* Take a shortcut for the common case */
286
27.4M
    if (!(c == 'e' || c == 'E' || exp10 < -NUM_POWERS_10)) { /* Check for trailing garbage */
287
27.4M
        if (c != EOFC)
288
23.6M
            *psp = sp, code = 1;
289
27.4M
        make_real(pref, ival * neg_powers_10[-exp10]);
290
27.4M
        return code;
291
27.4M
    }
292
23.5k
    dval = (double)ival;
293
23.5k
    goto fe;
294
295
    /* Now we are accumulating a double in dval. */
296
70.4k
fd:
297
385k
    while (IS_DIGIT(d, c)) {
298
314k
        dval = dval * 10 + d;
299
314k
        exp10--;
300
314k
        GET_NEXT(c, sp, c = EOFC);
301
314k
    }
302
73.3k
fs:
303
73.3k
    if (sign < 0)
304
14.0k
        dval = -dval;
305
464k
fe:
306
    /* Now dval contains the value, negated if necessary. */
307
464k
    switch (c) {
308
368k
        case 'e':
309
386k
        case 'E':
310
386k
            {     /* Check for a following exponent. */
311
386k
                int esign = 0;
312
386k
                int iexp;
313
314
386k
                GET_NEXT(c, sp, return_error(gs_error_syntaxerror));
315
222k
                switch (c) {
316
10.6k
                    case '-':
317
10.6k
                        esign = 1;
318
                        /* fall through */
319
19.2k
                    case '+':
320
19.2k
                        GET_NEXT(c, sp, return_error(gs_error_syntaxerror));
321
222k
                }
322
                /* Scan the exponent.  We limit it arbitrarily to 999. */
323
219k
                if (!IS_DIGIT(d, c))
324
175k
                    return_error(gs_error_syntaxerror);
325
44.0k
                iexp = d;
326
64.1k
                for (;; iexp = iexp * 10 + d) {
327
64.1k
                    GET_NEXT(c, sp, break);
328
54.5k
                    if (!IS_DIGIT(d, c)) {
329
34.3k
                        *psp = sp;
330
34.3k
                        code = 1;
331
34.3k
                        break;
332
34.3k
                    }
333
20.2k
                    if (iexp > 99)
334
102
                        return_error(gs_error_limitcheck);
335
20.2k
                }
336
43.9k
                if (esign)
337
10.2k
                    exp10 -= iexp;
338
33.6k
                else
339
33.6k
                    exp10 += iexp;
340
43.9k
                break;
341
44.0k
            }
342
74.2k
        default:
343
74.2k
            *psp = sp;
344
74.2k
            code = 1;
345
78.2k
        case EOFC:
346
78.2k
            ;
347
464k
    }
348
    /* Compute dval * 10^exp10. */
349
122k
    if (exp10 > 0) {
350
63.2k
        while (exp10 > NUM_POWERS_10)
351
36.6k
            dval *= powers_10[NUM_POWERS_10],
352
36.6k
                exp10 -= NUM_POWERS_10;
353
26.5k
        dval *= powers_10[exp10];
354
95.6k
    } else if (exp10 < 0) {
355
450k
        while (exp10 < -NUM_POWERS_10)
356
361k
            dval /= powers_10[NUM_POWERS_10],
357
361k
                exp10 += NUM_POWERS_10;
358
89.7k
        dval /= powers_10[-exp10];
359
89.7k
    }
360
    /*
361
     * Check for an out-of-range result.  Currently we don't check for
362
     * absurdly large numbers of digits in the accumulation loops,
363
     * but we should.
364
     */
365
122k
    if (dval >= 0) {
366
102k
        if (dval > MAX_FLOAT)
367
164
            return_error(gs_error_limitcheck);
368
102k
    } else {
369
19.8k
        if (dval < -MAX_FLOAT)
370
54
            return_error(gs_error_limitcheck);
371
19.8k
    }
372
174k
rret:
373
174k
    make_real(pref, dval);
374
174k
    return code;
375
122k
}