Coverage Report

Created: 2025-11-16 07:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/psi/ibnum.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
/* Level 2 encoded number reading utilities for Ghostscript */
18
#include "math_.h"
19
#include "memory_.h"
20
#include "ghost.h"
21
#include "opcheck.h"
22
#include "ierrors.h"
23
#include "stream.h"
24
#include "ibnum.h"
25
#include "imemory.h"    /* for iutil.h */
26
#include "iutil.h"
27
28
/* Define the number of bytes for a given format of encoded number. */
29
const byte enc_num_bytes[] = {
30
    enc_num_bytes_values
31
};
32
33
/* ------ Encoded number reading ------ */
34
35
/* Set up to read from an encoded number array/string. */
36
/* Return <0 for error, or a number format. */
37
int
38
num_array_format(const ref * op)
39
50
{
40
50
    int format;
41
42
50
    switch (r_type(op)) {
43
17
        case t_string:
44
17
            {
45
                /* Check that this is a legitimate encoded number string. */
46
17
                const byte *bp = op->value.bytes;
47
48
17
                if (r_size(op) < 4 || bp[0] != bt_num_array_value)
49
17
                    return_error(gs_error_typecheck);
50
0
                format = bp[1];
51
0
                if (!num_is_valid(format) ||
52
0
                    sdecodeshort(bp + 2, format) !=
53
0
                    (r_size(op) - 4) / encoded_number_bytes(format)
54
0
                    )
55
0
                    return_error(gs_error_rangecheck);
56
0
            }
57
0
            break;
58
27
        case t_array:
59
27
        case t_mixedarray:
60
27
        case t_shortarray:
61
27
            format = num_array;
62
27
            break;
63
6
        default:
64
6
            return_error(gs_error_typecheck);
65
50
    }
66
27
    check_read(*op);
67
27
    return format;
68
27
}
69
70
/* Get the number of elements in an encoded number array/string. */
71
uint
72
num_array_size(const ref * op, int format)
73
27
{
74
27
    return (format == num_array ? r_size(op) :
75
27
            (r_size(op) - 4) / encoded_number_bytes(format));
76
27
}
77
78
/* Get an encoded number from an array/string according to the given format. */
79
/* Put the value in np->value.{intval,realval}. */
80
/* Return t_int if integer, t_real if real, t_null if end of stream, */
81
/* or an error if the format is invalid. */
82
int
83
num_array_get(const gs_memory_t *mem, const ref * op, int format, uint index, ref * np)
84
1
{
85
1
    if (format == num_array) {
86
1
        int code = array_get(mem, op, (long)index, np);
87
88
1
        if (code < 0)
89
0
            return t_null;
90
1
        switch (r_type(np)) {
91
0
            case t_integer:
92
0
                return t_integer;
93
0
            case t_real:
94
0
                return t_real;
95
1
            default:
96
1
                return_error(gs_error_typecheck);
97
1
        }
98
1
    } else {
99
0
        uint nbytes = encoded_number_bytes(format);
100
101
0
        if (index >= (r_size(op) - 4) / nbytes)
102
0
            return t_null;
103
0
        return sdecode_number(op->value.bytes + 4 + index * nbytes,
104
0
                              format, np);
105
0
    }
106
1
}
107
108
/* Internal routine to decode a number in a given format. */
109
/* Same returns as sget_encoded_number. */
110
static const double binary_scale[32] = {
111
#define EXPN2(n) (0.5 / (1L << (n-1)))
112
    1.0, EXPN2(1), EXPN2(2), EXPN2(3),
113
    EXPN2(4), EXPN2(5), EXPN2(6), EXPN2(7),
114
    EXPN2(8), EXPN2(9), EXPN2(10), EXPN2(11),
115
    EXPN2(12), EXPN2(13), EXPN2(14), EXPN2(15),
116
    EXPN2(16), EXPN2(17), EXPN2(18), EXPN2(19),
117
    EXPN2(20), EXPN2(21), EXPN2(22), EXPN2(23),
118
    EXPN2(24), EXPN2(25), EXPN2(26), EXPN2(27),
119
    EXPN2(28), EXPN2(29), EXPN2(30), EXPN2(31)
120
#undef EXPN2
121
};
122
int
123
sdecode_number(const byte * str, int format, ref * np)
124
4.23M
{
125
4.23M
    switch (format & 0x170) {
126
1.14M
        case num_int32:
127
2.62M
        case num_int32 + 16:
128
2.62M
            if ((format & 31) == 0) {
129
287k
                np->value.intval = sdecodeint32(str, format);
130
287k
                return t_integer;
131
2.33M
            } else {
132
2.33M
                np->value.realval =
133
2.33M
                    (double)sdecodeint32(str, format) *
134
2.33M
                    binary_scale[format & 31];
135
2.33M
                return t_real;
136
2.33M
            }
137
569k
        case num_int16:
138
569k
            if ((format & 15) == 0) {
139
440k
                np->value.intval = sdecodeshort(str, format);
140
440k
                return t_integer;
141
440k
            } else {
142
129k
                np->value.realval =
143
129k
                    sdecodeshort(str, format) *
144
129k
                    binary_scale[format & 15];
145
129k
                return t_real;
146
129k
            }
147
1.03M
        case num_float:
148
1.03M
            {
149
1.03M
                float fval;
150
1.03M
                int code = sdecode_float(str, format, &fval);
151
152
1.03M
                if (code < 0)
153
43
                    return code;
154
1.03M
                np->value.realval = fval;
155
1.03M
                return t_real;
156
1.03M
            }
157
0
        default:
158
0
            return_error(gs_error_syntaxerror); /* invalid format?? */
159
4.23M
    }
160
4.23M
}
161
162
/* ------ Decode number ------ */
163
164
/* Decode encoded numbers from a string according to format. */
165
166
/* Decode a (16-bit, signed or unsigned) short. */
167
uint
168
sdecodeushort(const byte * p, int format)
169
644k
{
170
644k
    int a = p[0], b = p[1];
171
172
644k
    return (num_is_lsb(format) ? (b << 8) + a : (a << 8) + b);
173
644k
}
174
int
175
sdecodeshort(const byte * p, int format)
176
569k
{
177
569k
    int v = (int)sdecodeushort(p, format);
178
179
569k
    return (v & 0x7fff) - (v & 0x8000);
180
569k
}
181
182
/* Decode a (32-bit, signed) long. */
183
int
184
sdecodeint32(const byte * p, int format)
185
2.67M
{
186
2.67M
    int a = p[0], b = p[1], c = p[2], d = p[3];
187
2.67M
    int v = (num_is_lsb(format) ?
188
1.38M
              ((int)d << 24) + ((int)c << 16) + (b << 8) + a :
189
2.67M
              ((int)a << 24) + ((int)b << 16) + (c << 8) + d);
190
2.67M
    return v;
191
2.67M
}
192
193
/* Decode a 32-bit number. Return the resukt through a pointer */
194
/* to work around a gcc 4.2.1 bug on PowerPC, bug 689586 */
195
static void
196
sdecodebits32(const byte * p, int format, bits32 *v)
197
1.01M
{
198
1.01M
  int a = p[0], b = p[1], c = p[2], d = p[3];
199
1.01M
  *v = (num_is_lsb(format) ?
200
10.3k
            ((long)d << 24) + ((long)c << 16) + (b << 8) + a :
201
1.01M
            ((long)a << 24) + ((long)b << 16) + (c << 8) + d);
202
203
1.01M
}
204
205
/* Decode a float.  We assume that native floats occupy 32 bits. */
206
/* If the float is an IEEE NaN or Inf, return gs_error_undefinedresult. */
207
int
208
sdecode_float(const byte * p, int format, float *pfnum)
209
1.04M
{
210
1.04M
    bits32 lnum;
211
212
1.04M
    if ((format & ~(num_msb | num_lsb)) == num_float_native) {
213
        /*
214
         * Just read 4 bytes and interpret them as a float, ignoring
215
         * any indication of byte ordering.
216
         */
217
24.0k
        memcpy(pfnum, p, 4);
218
#if !ARCH_FLOATS_ARE_IEEE
219
        return 0;   /* no way to check for anomalies */
220
#endif
221
24.0k
        lnum = *(bits32 *)pfnum;
222
1.01M
    } else {
223
1.01M
        sdecodebits32(p, format, &lnum);
224
225
#if !ARCH_FLOATS_ARE_IEEE
226
        {
227
            /* We know IEEE floats take 32 bits. */
228
            /* Convert IEEE float to native float. */
229
            int sign_expt = lnum >> 23;
230
            int expt = sign_expt & 0xff;
231
            long mant = lnum & 0x7fffff;
232
            float fnum;
233
234
            if (expt == 0 && mant == 0)
235
                fnum = 0;
236
            else if (expt == 0xff)
237
                return_error(gs_error_undefinedresult); /* Inf or NaN */
238
            else {
239
                mant += 0x800000;
240
                fnum = (float)ldexp((float)mant, expt - 127 - 23);
241
            }
242
            if (sign_expt & 0x100)
243
                fnum = -fnum;
244
            *pfnum = fnum;
245
            return 0;   /* checked for Infs and NaNs above */
246
        }
247
#else
248
1.01M
        *pfnum = *(float *)&lnum;
249
1.01M
#endif
250
1.01M
    }
251
    /*
252
     * Unfortunately, there is no portable way for testing whether a float
253
     * is a NaN or Inf.  Do it "by hand" if the input representation is
254
     * IEEE (which is the case if control arrives here).
255
     */
256
1.04M
    if (!(~lnum & 0x7f800000))  /* i.e. exponent all 1's */
257
48
        return_error(gs_error_undefinedresult); /* Inf or NaN */
258
1.04M
    return 0;
259
1.04M
}