Coverage Report

Created: 2022-04-16 11:23

/src/ghostpdl/psi/iscannum.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2021 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.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, 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
22.1M
{
41
22.1M
    const byte *sp = str;
42
22.1M
#define GET_NEXT(cvar, sp, end_action)\
43
78.9M
  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
22.1M
#define NUM_POWERS_10 6
50
22.1M
    static const float powers_10[NUM_POWERS_10 + 1] = {
51
22.1M
        1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6
52
22.1M
    };
53
22.1M
    static const double neg_powers_10[NUM_POWERS_10 + 1] = {
54
22.1M
        1e0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6
55
22.1M
    };
56
57
22.1M
    ps_int ival;
58
22.1M
    double dval;
59
22.1M
    int exp10;
60
22.1M
    int code = 0;
61
22.1M
    int c, d;
62
22.1M
    ps_uint max_scan; /* max signed or unsigned int */
63
22.1M
    ps_int max_ps_int_scan, min_ps_int_scan;
64
22.1M
    const byte *const decoder = scan_char_decoder;
65
22.1M
#define IS_DIGIT(d, c)\
66
57.3M
  ((d = decoder[c]) < 10)
67
22.1M
#define WOULD_OVERFLOW(val, d, maxv)\
68
22.1M
  (val >= maxv / 10 && (val > maxv / 10 || d > (int64_t)(maxv % 10)))
69
70
22.1M
    GET_NEXT(c, sp, return_error(gs_error_syntaxerror));
71
22.1M
    if (!IS_DIGIT(d, c)) {
72
3.95M
        if (c != '.')
73
0
            return_error(gs_error_syntaxerror);
74
        /* Might be a number starting with '.'. */
75
3.95M
        GET_NEXT(c, sp, return_error(gs_error_syntaxerror));
76
3.95M
        if (!IS_DIGIT(d, c))
77
3.95M
            return_error(gs_error_syntaxerror);
78
8.19k
        ival = 0;
79
8.19k
        goto i2r;
80
3.95M
    }
81
    /* Accumulate an integer in ival. */
82
    /* Do up to 4 digits without a loop, */
83
    /* since we know this can't overflow and since */
84
    /* most numbers have 4 (integer) digits or fewer. */
85
18.1M
    ival = d;
86
18.1M
    if (end - sp >= 3) { /* just check once */
87
17.6M
        if (!IS_DIGIT(d, (c = *sp))) {
88
6.05M
            sp++;
89
6.05M
            goto ind;
90
6.05M
        }
91
11.6M
        ival = ival * 10 + d;
92
11.6M
        if (!IS_DIGIT(d, (c = sp[1]))) {
93
11.1M
            sp += 2;
94
11.1M
            goto ind;
95
11.1M
        }
96
414k
        ival = ival * 10 + d;
97
414k
        sp += 3;
98
414k
        if (!IS_DIGIT(d, (c = sp[-1])))
99
229k
            goto ind;
100
185k
        ival = ival * 10 + d;
101
185k
    }
102
103
698k
    max_ps_int_scan = scanner_options & SCAN_CPSI_MODE ? MAX_PS_INT32 : MAX_PS_INT;
104
698k
    min_ps_int_scan = scanner_options & SCAN_CPSI_MODE ? MIN_PS_INT32 : MIN_PS_INT;
105
106
698k
    max_scan = scanner_options & SCAN_PDF_UNSIGNED && sign >= 0 ? ~((ps_int)0) : max_ps_int_scan;
107
108
963k
    for (;; ival = ival * 10 + d) {
109
963k
        GET_NEXT(c, sp, goto iret);
110
420k
        if (!IS_DIGIT(d, c))
111
155k
            break;
112
264k
        if (WOULD_OVERFLOW(((ps_uint)ival), d, max_scan)) {
113
0
            if (ival == max_ps_int_scan / 10 && d == (max_ps_int_scan % 10) + 1 && sign < 0) {
114
0
                GET_NEXT(c, sp, c = EOFC);
115
0
                dval = -(double)min_ps_int_scan;
116
0
                if (c == 'e' || c == 'E') {
117
0
                    exp10 = 0;
118
0
                    goto fs;
119
0
                } else if (c == '.') {
120
0
                    GET_NEXT(c, sp, c = EOFC);
121
0
                    exp10 = 0;
122
0
                    goto fd;
123
0
                } else if (!IS_DIGIT(d, c)) {
124
0
                    ival = min_ps_int_scan;
125
0
                    break;
126
0
                }
127
0
            } else
128
0
                dval = (double)ival;
129
0
            goto l2d;
130
0
        }
131
264k
    }
132
17.6M
  ind:        /* We saw a non-digit while accumulating an integer in ival. */
133
17.6M
    switch (c) {
134
129k
        case '.':
135
129k
            GET_NEXT(c, sp, c = EOFC);
136
129k
            goto i2r;
137
6.70M
        default:
138
6.70M
            *psp = sp;
139
6.70M
            code = 1;
140
6.70M
            break;
141
0
        case EOFC:
142
0
            break;
143
1.57k
        case 'e':
144
1.57k
        case 'E':
145
1.57k
            if (sign < 0)
146
0
                ival = -ival;
147
1.57k
            dval = (double)ival;
148
1.57k
            exp10 = 0;
149
1.57k
            goto fe;
150
10.8M
        case '#':
151
10.8M
            {
152
10.8M
                const int radix = ival;
153
10.8M
                ps_int uval = 0, imax;
154
155
10.8M
                if (sign || radix < min_radix || radix > max_radix)
156
0
                    return_error(gs_error_syntaxerror);
157
                /* Avoid multiplies for power-of-2 radix. */
158
10.8M
                if (!(radix & (radix - 1))) {
159
10.8M
                    int shift;
160
161
10.8M
                    switch (radix) {
162
683
                        case 2:
163
683
                            shift = 1, imax = MAX_PS_UINT >> 1;
164
683
                            break;
165
0
                        case 4:
166
0
                            shift = 2, imax = MAX_PS_UINT >> 2;
167
0
                            break;
168
0
                        case 8:
169
0
                            shift = 3, imax = MAX_PS_UINT >> 3;
170
0
                            break;
171
10.8M
                        case 16:
172
10.8M
                            shift = 4, imax = MAX_PS_UINT >> 4;
173
10.8M
                            break;
174
0
                        case 32:
175
0
                            shift = 5, imax = MAX_PS_UINT >> 5;
176
0
                            break;
177
0
                        default:  /* can't happen */
178
0
                            return_error(gs_error_rangecheck);
179
10.8M
                    }
180
51.3M
                    for (;; uval = (uval << shift) + d) {
181
51.3M
                        GET_NEXT(c, sp, break);
182
45.9M
                        d = decoder[c];
183
45.9M
                        if (d >= radix) {
184
5.41M
                            *psp = sp;
185
5.41M
                            code = 1;
186
5.41M
                            break;
187
5.41M
                        }
188
40.5M
                        if (uval > imax)
189
0
                            return_error(gs_error_limitcheck);
190
40.5M
                    }
191
10.8M
                } else {
192
0
                    ps_int irem = MAX_PS_UINT % radix;
193
194
0
                    imax = MAX_PS_UINT / radix;
195
0
                    for (;; uval = uval * radix + d) {
196
0
                        GET_NEXT(c, sp, break);
197
0
                        d = decoder[c];
198
0
                        if (d >= radix) {
199
0
                            *psp = sp;
200
0
                            code = 1;
201
0
                            break;
202
0
                        }
203
0
                        if (uval >= imax &&
204
0
                            (uval > imax || d > irem)
205
0
                            )
206
0
                            return_error(gs_error_limitcheck);
207
0
                    }
208
0
                }
209
10.8M
                if (scanner_options & SCAN_CPSI_MODE) {
210
0
                    ps_uint32 int1 = 0;
211
0
                    int1 |= (uval & 0xffffffff);
212
0
                    make_int(pref, (ps_int)((ps_int32)int1));
213
0
                }
214
10.8M
                else
215
10.8M
                    make_int(pref, uval);
216
217
10.8M
                return code;
218
10.8M
            }
219
17.6M
    }
220
7.24M
iret:
221
7.24M
    if (scanner_options & SCAN_CPSI_MODE) {
222
0
        make_int(pref, (sign < 0 ? (ps_int32)-ival : (ps_int32)ival));
223
0
    }
224
7.24M
    else {
225
7.24M
        make_int(pref, (sign < 0 ? (ps_int)-ival : (ps_int)ival));
226
7.24M
    }
227
7.24M
    return code;
228
229
    /* Accumulate a double in dval. */
230
0
l2d:
231
0
    exp10 = 0;
232
0
    for (;;) {
233
0
        dval = dval * 10 + d;
234
0
        GET_NEXT(c, sp, c = EOFC);
235
0
        if (!IS_DIGIT(d, c))
236
0
            break;
237
0
    }
238
0
    switch (c) {
239
0
        case '.':
240
0
            GET_NEXT(c, sp, c = EOFC);
241
0
            exp10 = 0;
242
0
            goto fd;
243
0
        default:
244
0
            *psp = sp;
245
0
            code = 1;
246
            /* falls through */
247
0
        case EOFC:
248
0
            if (sign < 0)
249
0
                dval = -dval;
250
0
            goto rret;
251
0
        case 'e':
252
0
        case 'E':
253
0
            exp10 = 0;
254
0
            goto fs;
255
0
        case '#':
256
0
            return_error(gs_error_syntaxerror);
257
0
    }
258
259
    /* We saw a '.' while accumulating an integer in ival. */
260
137k
i2r:
261
137k
    exp10 = 0;
262
553k
    while (IS_DIGIT(d, c) || c == '-') {
263
        /*
264
         * PostScript gives an error on numbers with a '-' following a '.'
265
         * Adobe Acrobat Reader (PDF) apparently doesn't treat this as an
266
         * error. Experiments show that the numbers following the '-' are
267
         * ignored, so we swallow the fractional part. SCAN_PDF_INV_NUM
268
         *  enables this compatibility kloodge.
269
         */
270
415k
        if (c == '-') {
271
0
            if ((SCAN_PDF_INV_NUM & scanner_options) == 0)
272
0
                break;
273
0
            do {
274
0
                GET_NEXT(c, sp, c = EOFC);
275
0
            } while (IS_DIGIT(d, c));
276
0
            break;
277
0
        }
278
415k
        if (WOULD_OVERFLOW(ival, d, max_int)) {
279
64
            dval = (double)ival;
280
64
            goto fd;
281
64
        }
282
415k
        ival = ival * 10 + d;
283
415k
        exp10--;
284
415k
        GET_NEXT(c, sp, c = EOFC);
285
415k
    }
286
137k
    if (sign < 0)
287
6.83k
        ival = -ival;
288
    /* Take a shortcut for the common case */
289
137k
    if (!(c == 'e' || c == 'E' || exp10 < -NUM_POWERS_10)) { /* Check for trailing garbage */
290
128k
        if (c != EOFC)
291
121k
            *psp = sp, code = 1;
292
128k
        make_real(pref, ival * neg_powers_10[-exp10]);
293
128k
        return code;
294
128k
    }
295
8.87k
    dval = (double)ival;
296
8.87k
    goto fe;
297
298
    /* Now we are accumulating a double in dval. */
299
64
fd:
300
156
    while (IS_DIGIT(d, c)) {
301
92
        dval = dval * 10 + d;
302
92
        exp10--;
303
92
        GET_NEXT(c, sp, c = EOFC);
304
92
    }
305
64
fs:
306
64
    if (sign < 0)
307
0
        dval = -dval;
308
10.5k
fe:
309
    /* Now dval contains the value, negated if necessary. */
310
10.5k
    switch (c) {
311
1.63k
        case 'e':
312
1.63k
        case 'E':
313
1.63k
            {     /* Check for a following exponent. */
314
1.63k
                int esign = 0;
315
1.63k
                int iexp;
316
317
1.63k
                GET_NEXT(c, sp, return_error(gs_error_syntaxerror));
318
1.63k
                switch (c) {
319
0
                    case '-':
320
0
                        esign = 1;
321
                        /* fall through */
322
0
                    case '+':
323
0
                        GET_NEXT(c, sp, return_error(gs_error_syntaxerror));
324
1.63k
                }
325
                /* Scan the exponent.  We limit it arbitrarily to 999. */
326
1.63k
                if (!IS_DIGIT(d, c))
327
0
                    return_error(gs_error_syntaxerror);
328
1.63k
                iexp = d;
329
3.00k
                for (;; iexp = iexp * 10 + d) {
330
3.00k
                    GET_NEXT(c, sp, break);
331
2.32k
                    if (!IS_DIGIT(d, c)) {
332
955
                        *psp = sp;
333
955
                        code = 1;
334
955
                        break;
335
955
                    }
336
1.36k
                    if (iexp > 99)
337
0
                        return_error(gs_error_limitcheck);
338
1.36k
                }
339
1.63k
                if (esign)
340
0
                    exp10 -= iexp;
341
1.63k
                else
342
1.63k
                    exp10 += iexp;
343
1.63k
                break;
344
1.63k
            }
345
7.51k
        default:
346
7.51k
            *psp = sp;
347
7.51k
            code = 1;
348
8.88k
        case EOFC:
349
8.88k
            ;
350
10.5k
    }
351
    /* Compute dval * 10^exp10. */
352
10.5k
    if (exp10 > 0) {
353
3.21k
        while (exp10 > NUM_POWERS_10)
354
1.57k
            dval *= powers_10[NUM_POWERS_10],
355
1.57k
                exp10 -= NUM_POWERS_10;
356
1.63k
        dval *= powers_10[exp10];
357
8.88k
    } else if (exp10 < 0) {
358
17.7k
        while (exp10 < -NUM_POWERS_10)
359
8.88k
            dval /= powers_10[NUM_POWERS_10],
360
8.88k
                exp10 += NUM_POWERS_10;
361
8.88k
        dval /= powers_10[-exp10];
362
8.88k
    }
363
    /*
364
     * Check for an out-of-range result.  Currently we don't check for
365
     * absurdly large numbers of digits in the accumulation loops,
366
     * but we should.
367
     */
368
10.5k
    if (dval >= 0) {
369
10.5k
        if (dval > MAX_FLOAT)
370
0
            return_error(gs_error_limitcheck);
371
10.5k
    } else {
372
0
        if (dval < -MAX_FLOAT)
373
0
            return_error(gs_error_limitcheck);
374
0
    }
375
10.5k
rret:
376
10.5k
    make_real(pref, dval);
377
10.5k
    return code;
378
10.5k
}