Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/base/gsserial.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
/* some utilities useful for converting objects to serial form */
17
18
#include "stdpre.h"
19
#include "gstypes.h"
20
#include "gsserial.h"
21
22
/*
23
 * Procedures for converint between integers and a variable-length,
24
 * little-endian string representation thereof. This scheme uses a
25
 * base-128 format with the high-order bit of each byte used as a
26
 * continuation flag ((b & 0x80) == 0 ==> this is the last byte of the
27
 * current number). See gsserial.h for complete information.
28
 */
29
30
/*
31
 * Determine the size of the string representation of an unsigned or
32
 * signed integer.
33
 */
34
int
35
enc_u_size_uint(uint uval)
36
118k
{
37
118k
    int     i = 1;
38
39
368k
    while ((uval >>= enc_u_shift) > 0)
40
249k
        ++i;
41
118k
    return i;
42
118k
}
43
44
int
45
enc_s_size_int(int ival)
46
0
{
47
    /* MIN_INT must be handled specially */
48
0
    if (ival < 0) {
49
0
        if (ival == enc_s_min_int)
50
0
            return enc_s_sizew_max;
51
0
        ival = -ival;
52
0
    }
53
0
    return enc_u_sizew((uint)ival << 1);
54
0
}
55
56
/*
57
 * Encode a signed or unsigned integer. The array pointed to by ptr is
58
 * assumed to be large enough. The returned pointer immediately follows
59
 * the encoded number.
60
 */
61
byte *
62
enc_u_put_uint(uint uval, byte * ptr)
63
57.9k
{
64
57.9k
    int     tmp_v;
65
66
177k
    for (;;) {
67
177k
        tmp_v = uval & (enc_u_lim_1b - 1);
68
177k
        if ((uval >>= enc_u_shift) == 0)
69
57.9k
            break;
70
119k
        *ptr++ = tmp_v | enc_u_lim_1b;
71
119k
    }
72
57.9k
    *ptr++ = tmp_v;
73
57.9k
    return ptr;
74
57.9k
}
75
76
byte *
77
enc_s_put_int(int ival, byte * ptr)
78
0
{
79
0
    uint    uval, tmp_v;
80
81
    /* MIN_INT must be handled specially */
82
0
    if (ival < 0 && ival != enc_s_min_int)
83
0
        uval = (uint)-ival;
84
0
    else
85
0
        uval = (uint)ival;
86
87
0
    tmp_v = (uval & enc_s_max_1b) | (ival < 0 ? enc_s_max_1b + 1 : 0);
88
0
    if (uval > enc_s_max_1b) {
89
0
        *ptr++ = tmp_v | enc_u_lim_1b;
90
0
        return enc_u_put_uint(uval >> enc_s_shift0, ptr);
91
0
    } else {
92
0
        *ptr++ = tmp_v;
93
0
        return ptr;
94
0
    }
95
0
}
96
97
/*
98
 * Decode an integer string for a signed or unsigned integer. Note that
99
 * two forms of this procedure are provide, to allow both const and non-
100
 * const byte pointers to be handled (the former is far more common).
101
 */
102
const byte *
103
enc_u_get_uint(uint * pval, const byte * ptr)
104
7.61M
{
105
7.61M
    uint    uval = 0, tmp_val;
106
7.61M
    int     shift = 0;
107
108
18.9M
    while (((tmp_val = *ptr++) & enc_u_lim_1b) != 0) {
109
11.3M
        uval |= (tmp_val & (enc_u_lim_1b - 1)) << shift;
110
11.3M
        shift += enc_u_shift;
111
11.3M
    }
112
7.61M
    *pval = uval | (tmp_val << shift);
113
114
7.61M
    return ptr;
115
7.61M
}
116
117
byte *
118
enc_u_get_uint_nc(uint * pval, byte * ptr)
119
0
{
120
0
    const byte *    tmp_ptr = ptr;
121
122
0
    tmp_ptr = enc_u_get_uint(pval, tmp_ptr);
123
0
    return ptr += tmp_ptr - ptr;
124
0
}
125
126
const byte *
127
enc_s_get_int(int * pval, const byte * ptr)
128
0
{
129
0
    int     ival = *ptr++;
130
0
    bool    neg = false;
131
132
0
    if ((ival & (enc_s_max_1b + 1)) != 0) {
133
0
        ival ^= enc_s_max_1b + 1;
134
0
        neg = true;
135
0
    }
136
0
    if ((ival & enc_u_lim_1b) != 0) {
137
0
        uint     tmp_val;
138
139
0
        ival ^= enc_u_lim_1b;
140
0
        ptr = enc_u_get_uint(&tmp_val, ptr);
141
0
        ival |= tmp_val << enc_s_shift0;
142
0
    }
143
0
    if (neg && ival >= 0)    /* >= check required for enc_s_min_int */
144
0
        ival = -ival;
145
146
0
    *pval = ival;
147
0
    return ptr;
148
0
}
149
150
byte *
151
enc_s_get_int_nc(int * pval, byte * ptr)
152
0
{
153
0
    const byte *    tmp_ptr = ptr;
154
155
0
    tmp_ptr = enc_s_get_int(pval, tmp_ptr);
156
0
    return ptr += tmp_ptr - ptr;
157
0
}
158
159
#ifdef UNIT_TEST
160
161
#include <stdio.h>
162
#include <string.h>
163
164
/*
165
 * Encoding and decoding of integers is verified using a round-trip process,
166
 * integer ==> string ==> integer. The string size is separately checked to
167
 * verify that it is not too large (it can't be too small if the round-trip
168
 * check works). If an integer x is represented by nbytes, then it must be
169
 * that x >= 1U << (7 * (n - 1)) (unsigned; 1U << (7 * (n - 2) + 6) for
170
 * signed integers; there is no need to check 1-byte encodings).
171
 *
172
 * It is possible to check every value, but this is not necessary. Any
173
 * failures that arise will do so in the vicinty of powers of 2.
174
 */
175
176
/* check the length of an encoded string */
177
void
178
check_u_sizew(uint uval, int len)
179
{
180
    if (len != enc_u_sizew(uval))
181
        fprintf( stderr,
182
                 "Size calculation error for (usigned) %u (%d != %d)\n",
183
                 uval,
184
                 len,
185
                 enc_u_sizew(uval) );
186
    if ( len > 1                                                           &&
187
         (len > enc_u_sizew_max  || uval < 1U << (enc_u_shift * (len - 1)))  )
188
        fprintf( stderr, "unsigned encoding too large for %u (%d bytes)\n",
189
                 uval,
190
                 len );
191
}
192
193
void
194
check_s_sizew(int ival, int len)
195
{
196
    uint    uval;
197
198
    if (len != enc_s_sizew(ival))
199
        fprintf( stderr,
200
                 "Size calculation error for (signed) %d (%d != %d)\n",
201
                 ival,
202
                 len,
203
                 enc_s_sizew(ival) );
204
    if (len <= 1)
205
        return;
206
    if (ival < 0 && ival != enc_s_min_int)
207
        uval = (uint)-ival;
208
    else
209
        uval = (uint)ival;
210
    if ( len > enc_s_sizew_max                                 ||
211
         uval < 1U << (enc_s_shift1 * (len - 2) + enc_s_shift0)  )
212
        fprintf( stderr,
213
                 "signed encoding too large for %d (%d bytes)\n",
214
                 ival,
215
                 len );
216
}
217
218
/* check the encode and decode procedures on a value */
219
void
220
check_u(uint uval)
221
{
222
    byte            buff[32];   /* generous size */
223
    byte *          cp0 = buff;
224
    const byte *    cp1 = buff;
225
    byte *          cp2 = buff;
226
    uint            res_val;
227
228
    memset(buff, 0, sizeof(buff));
229
    enc_u_putw(uval, cp0);
230
    check_u_sizew(uval, cp0 - buff);
231
    memset(cp0, (uval == 0 ? 0x7f : 0), sizeof(buff) - (cp0 - buff));
232
233
    enc_u_getw(res_val, cp1);
234
    if (cp1 != cp0)
235
        fprintf( stderr,
236
                 "encoded length disparity (const) for "
237
                 "(unsigned) %u (%d != %d)\n",
238
                 uval,
239
                 cp0 - buff,
240
                 cp1 - buff );
241
    if (res_val != uval)
242
        fprintf( stderr,
243
                 "decode error (const) for (unsigned) %u (!= %u)\n",
244
                 uval,
245
                 res_val );
246
247
    enc_u_getw_nc(res_val, cp2);
248
    if (cp2 != cp0)
249
        fprintf( stderr,
250
                 "encoded length disparity (non-const) for "
251
                 "(unsigned) %u (%d != %d)\n",
252
                 uval,
253
                 cp0 - buff,
254
                 cp1 - buff );
255
    if (res_val != uval)
256
        fprintf( stderr,
257
                 "decode error (non-const) for (unsigned) %u (!= %u)\n",
258
                 uval,
259
                 res_val );
260
}
261
262
void
263
check_s(int ival)
264
{
265
    byte            buff[32];   /* generous size */
266
    byte *          cp0 = buff;
267
    const byte *    cp1 = buff;
268
    byte *          cp2 = buff;
269
    int             res_val;
270
271
    memset(buff, 0, sizeof(buff));
272
    enc_s_putw(ival, cp0);
273
    check_s_sizew(ival, cp0 - buff);
274
    memset(cp0, (ival == 0 ? 0x7f : 0), sizeof(buff) - (cp0 - buff));
275
276
    enc_s_getw(res_val, cp1);
277
    if (cp1 != cp0)
278
        fprintf( stderr,
279
                 "encoded length disparity (const) for "
280
                 "(signed) %d (%d != %d)\n",
281
                 ival,
282
                 cp0 - buff,
283
                 cp1 - buff );
284
    if (res_val != ival)
285
        fprintf( stderr,
286
                 "decode error (const) for (signed) %d (!= %d)\n",
287
                 ival,
288
                 res_val );
289
290
    enc_s_getw_nc(res_val, cp2);
291
    if (cp1 != cp0)
292
        fprintf( stderr,
293
                 "encoded length disparity (non-const) for "
294
                 "(signed) %d (%d != %d)\n",
295
                 ival,
296
                 cp0 - buff,
297
                 cp1 - buff );
298
    if (res_val != ival)
299
        fprintf( stderr,
300
                 "decode error (non-const) for (unsigned) %d (!= %d)\n",
301
                 ival,
302
                 res_val );
303
}
304
305
/* test the provided value and some surrounding values */
306
void
307
check_u_vals(uint uval)
308
{
309
    uint    diff = 1;
310
311
    check_u(uval);
312
    do {
313
        check_u(uval - diff);
314
        check_u(uval + diff);
315
    } while ((diff <<= 1) < uval);
316
}
317
318
void
319
check_s_vals(int ival)
320
{
321
    int     diff = 1;
322
323
    check_s(ival);
324
    if (ival == enc_s_min_int) {
325
        do {
326
            check_s(ival - diff);
327
            check_s(ival + diff);
328
        } while ((diff <<= 1) != enc_s_min_int);
329
    } else {
330
        int     abs_val = (ival < 0 ? -ival : ival);
331
332
        do {
333
            check_s(ival - diff);
334
            check_s(ival + diff);
335
        } while ((diff <<= 1) < abs_val);
336
    }
337
}
338
339
int
340
main(void)
341
{
342
    uint     uval;
343
    int      ival;
344
345
    check_u_vals(0);
346
    for (uval = 1; uval != 0; uval <<= 1)
347
        check_u_vals(uval);
348
349
    check_s_vals(0);
350
    for (ival = 1; ival != 0; ival <<= 1) {
351
        check_s_vals(ival);
352
        if (ival != enc_s_min_int)
353
            check_s_vals(-ival);
354
    }
355
356
    fprintf(stderr, "all done\n");
357
    return 0;
358
}
359
360
#endif  /* UNIT_TEST */