Coverage Report

Created: 2025-06-10 07:26

/src/ghostpdl/base/gsutil.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
17
/* Utilities for Ghostscript library */
18
19
#include "string_.h"
20
#include "memory_.h"
21
#include "gstypes.h"
22
#include "gserrors.h"
23
#include "gsmemory.h"   /* for init procedure */
24
#include "gsrect.h"   /* for prototypes */
25
#include "gsuid.h"
26
#include "gsutil.h"   /* for prototypes */
27
#include "gxsync.h"   /* for gx_monitor_t */
28
29
/* ------ Unique IDs ------ */
30
31
/* This is used by multiple threads, so lock around updates */
32
ulong
33
gs_next_ids(const gs_memory_t *mem, uint count)
34
33.9M
{
35
33.9M
    gs_lib_ctx_core_t *core = mem->gs_lib_ctx->core;
36
33.9M
    ulong id;
37
38
33.9M
    gx_monitor_enter((gx_monitor_t *)(core->monitor));
39
33.9M
    id = core->gs_next_id;
40
33.9M
    core->gs_next_id += count;
41
33.9M
    gx_monitor_leave((gx_monitor_t *)(core->monitor));
42
43
33.9M
    return id;
44
33.9M
}
45
46
/* ------ Memory utilities ------ */
47
48
/* Transpose an 8 x 8 block of bits.  line_size is the raster of */
49
/* the input data.  dist is the distance between output bytes. */
50
51
void
52
memflip8x8(const byte * inp, int line_size, byte * outp, int dist)
53
60.1k
{
54
60.1k
    uint aceg, bdfh;
55
56
60.1k
    {
57
60.1k
        const byte *ptr4 = inp + (line_size << 2);
58
60.1k
        const int ls2 = line_size << 1;
59
60
60.1k
        aceg = ((uint)*inp) | ((uint)inp[ls2] << 8) |
61
60.1k
            ((uint)*ptr4 << 16) | ((uint)ptr4[ls2] << 24);
62
60.1k
        inp += line_size, ptr4 += line_size;
63
60.1k
        bdfh = ((uint)*inp) | ((uint)inp[ls2] << 8) |
64
60.1k
            ((uint)*ptr4 << 16) | ((uint)ptr4[ls2] << 24);
65
60.1k
    }
66
67
    /* Check for all 8 bytes being the same. */
68
    /* This is especially worth doing for the case where all are zero. */
69
60.1k
    if (aceg == bdfh && (aceg >> 8) == (aceg & 0xffffff)) {
70
27.6k
        if (aceg == 0 || aceg == 0xffffffff)
71
26.9k
            goto store;
72
767
        *outp = (byte)-(int)((aceg >> 7) & 1);
73
767
        outp[dist] = (byte)-(int)((aceg >> 6) & 1);
74
767
        outp += dist << 1;
75
767
        *outp = (byte)-(int)((aceg >> 5) & 1);
76
767
        outp[dist] = (byte)-(int)((aceg >> 4) & 1);
77
767
        outp += dist << 1;
78
767
        *outp = (byte)-(int)((aceg >> 3) & 1);
79
767
        outp[dist] = (byte)-(int)((aceg >> 2) & 1);
80
767
        outp += dist << 1;
81
767
        *outp = (byte)-(int)((aceg >> 1) & 1);
82
767
        outp[dist] = (byte)-(int)(aceg & 1);
83
767
        return;
84
32.4k
    } {
85
32.4k
        register uint temp;
86
87
/* Transpose a block of bits between registers. */
88
32.4k
#define TRANSPOSE(r,s,mask,shift)\
89
162k
  (r ^= (temp = ((s >> shift) ^ r) & mask),\
90
162k
   s ^= temp << shift)
91
92
/* Transpose blocks of 4 x 4 */
93
32.4k
        TRANSPOSE(aceg, aceg, 0x00000f0f, 20);
94
32.4k
        TRANSPOSE(bdfh, bdfh, 0x00000f0f, 20);
95
96
/* Transpose blocks of 2 x 2 */
97
32.4k
        TRANSPOSE(aceg, aceg, 0x00330033, 10);
98
32.4k
        TRANSPOSE(bdfh, bdfh, 0x00330033, 10);
99
100
/* Transpose blocks of 1 x 1 */
101
32.4k
        TRANSPOSE(aceg, bdfh, 0x55555555, 1);
102
103
32.4k
#undef TRANSPOSE
104
32.4k
    }
105
106
59.3k
  store:
107
59.3k
    *outp = (byte)aceg;
108
59.3k
    outp[dist] = (byte)bdfh;
109
59.3k
    outp += dist << 1;
110
59.3k
    *outp = (byte)(aceg >>= 8);
111
59.3k
    outp[dist] = (byte)(bdfh >>= 8);
112
59.3k
    outp += dist << 1;
113
59.3k
    *outp = (byte)(aceg >>= 8);
114
59.3k
    outp[dist] = (byte)(bdfh >>= 8);
115
59.3k
    outp += dist << 1;
116
59.3k
    *outp = (byte)(aceg >> 8);
117
59.3k
    outp[dist] = (byte)(bdfh >> 8);
118
59.3k
}
119
120
#ifdef PACIFY_VALGRIND
121
void
122
memflip8x8_eol(const byte * inp, int line_size, byte * outp, int dist, int bits)
123
25.3k
{
124
25.3k
    uint aceg, bdfh;
125
25.3k
    uint mask;
126
127
25.3k
    {
128
25.3k
        const byte *ptr4 = inp + (line_size << 2);
129
25.3k
        const int ls2 = line_size << 1;
130
131
25.3k
        aceg = ((uint)*inp) | ((uint)inp[ls2] << 8) |
132
25.3k
            ((uint)*ptr4 << 16) | ((uint)ptr4[ls2] << 24);
133
25.3k
        inp += line_size, ptr4 += line_size;
134
25.3k
        bdfh = ((uint)*inp) | ((uint)inp[ls2] << 8) |
135
25.3k
            ((uint)*ptr4 << 16) | ((uint)ptr4[ls2] << 24);
136
25.3k
    }
137
138
    /* Keep just the defined bits */
139
25.3k
    mask = (0xff00>>(bits&7)) & 0xff;
140
25.3k
    mask |= mask<<8;
141
25.3k
    mask |= mask<<16;
142
25.3k
    aceg &= mask;
143
25.3k
    bdfh &= mask;
144
145
    /* Check for all 8 bytes being the same. */
146
    /* This is especially worth doing for the case where all are zero. */
147
25.3k
    if (aceg == bdfh && (aceg >> 8) == (aceg & 0xffffff)) {
148
6.65k
        if (aceg == 0 || aceg == 0xffffffff)
149
5.60k
            goto store;
150
1.05k
        *outp = (byte)-(int)((aceg >> 7) & 1);
151
1.05k
        outp[dist] = (byte)-(int)((aceg >> 6) & 1);
152
1.05k
        outp += dist << 1;
153
1.05k
        *outp = (byte)-(int)((aceg >> 5) & 1);
154
1.05k
        outp[dist] = (byte)-(int)((aceg >> 4) & 1);
155
1.05k
        outp += dist << 1;
156
1.05k
        *outp = (byte)-(int)((aceg >> 3) & 1);
157
1.05k
        outp[dist] = (byte)-(int)((aceg >> 2) & 1);
158
1.05k
        outp += dist << 1;
159
1.05k
        *outp = (byte)-(int)((aceg >> 1) & 1);
160
1.05k
        outp[dist] = (byte)-(int)(aceg & 1);
161
1.05k
        return;
162
18.6k
    } {
163
18.6k
        register uint temp;
164
165
/* Transpose a block of bits between registers. */
166
18.6k
#define TRANSPOSE(r,s,mask,shift)\
167
93.4k
  (r ^= (temp = ((s >> shift) ^ r) & mask),\
168
93.4k
   s ^= temp << shift)
169
170
/* Transpose blocks of 4 x 4 */
171
18.6k
        TRANSPOSE(aceg, aceg, 0x00000f0f, 20);
172
18.6k
        TRANSPOSE(bdfh, bdfh, 0x00000f0f, 20);
173
174
/* Transpose blocks of 2 x 2 */
175
18.6k
        TRANSPOSE(aceg, aceg, 0x00330033, 10);
176
18.6k
        TRANSPOSE(bdfh, bdfh, 0x00330033, 10);
177
178
/* Transpose blocks of 1 x 1 */
179
18.6k
        TRANSPOSE(aceg, bdfh, 0x55555555, 1);
180
181
18.6k
#undef TRANSPOSE
182
18.6k
    }
183
184
24.3k
  store:
185
24.3k
    *outp = (byte)aceg;
186
24.3k
    outp[dist] = (byte)bdfh;
187
24.3k
    outp += dist << 1;
188
24.3k
    *outp = (byte)(aceg >>= 8);
189
24.3k
    outp[dist] = (byte)(bdfh >>= 8);
190
24.3k
    outp += dist << 1;
191
24.3k
    *outp = (byte)(aceg >>= 8);
192
24.3k
    outp[dist] = (byte)(bdfh >>= 8);
193
24.3k
    outp += dist << 1;
194
24.3k
    *outp = (byte)(aceg >> 8);
195
24.3k
    outp[dist] = (byte)(bdfh >> 8);
196
24.3k
}
197
#endif
198
199
/* Get an unsigned, big-endian 32-bit value. */
200
ulong
201
get_u32_msb(const byte *p)
202
42.1M
{
203
42.1M
    return ((uint)p[0] << 24) + ((uint)p[1] << 16) + ((uint)p[2] << 8) + p[3];
204
42.1M
}
205
206
/* Put an unsigned, big-endian 32-bit value. */
207
void
208
put_u32_msb(byte *p, const ulong n, const int offs)
209
0
{
210
0
    (p + offs)[0] = n >> 24 & 255;
211
0
    (p + offs)[1] = n >> 16 & 255;
212
0
    (p + offs)[2] = n >> 8  & 255;
213
0
    (p + offs)[3] = n & 255;
214
0
}
215
216
/* ------ String utilities ------ */
217
218
/* Compare two strings, returning -1 if the first is less, */
219
/* 0 if they are equal, and 1 if first is greater. */
220
/* We can't use memcmp, because we always use unsigned characters. */
221
int
222
bytes_compare(const byte * s1, uint len1, const byte * s2, uint len2)
223
16.0M
{
224
16.0M
    register uint len = len1;
225
226
16.0M
    if (len2 < len)
227
4.43M
        len = len2;
228
16.0M
    {
229
16.0M
        register const byte *p1 = s1;
230
16.0M
        register const byte *p2 = s2;
231
232
76.7M
        while (len--)
233
71.0M
            if (*p1++ != *p2++)
234
10.2M
                return (p1[-1] < p2[-1] ? -1 : 1);
235
16.0M
    }
236
    /* Now check for differing lengths */
237
5.74M
    return (len1 == len2 ? 0 : len1 < len2 ? -1 : 1);
238
16.0M
}
239
240
/* Test whether a string matches a pattern with wildcards. */
241
/* '*' = any substring, '?' = any character, '\' quotes next character. */
242
const string_match_params string_match_params_default = {
243
    '*', '?', '\\', false, false
244
};
245
246
bool
247
string_match(const byte * str, uint len, const byte * pstr, uint plen,
248
             register const string_match_params * psmp)
249
7.44M
{
250
7.44M
    const byte *pback = 0;
251
7.44M
    const byte *spback = 0; /* initialized only to pacify gcc */
252
7.44M
    const byte *p = pstr, *pend = pstr + plen;
253
7.44M
    const byte *sp = str, *spend = str + len;
254
255
7.44M
    if (psmp == 0)
256
7.44M
        psmp = &string_match_params_default;
257
50.7M
  again:while (p < pend) {
258
50.6M
        register byte ch = *p;
259
260
50.6M
        if (ch == psmp->any_substring) {
261
18.4k
            pback = ++p, spback = sp;
262
18.4k
            continue;
263
50.6M
        } else if (ch == psmp->any_char) {
264
0
            if (sp == spend)
265
0
                return false; /* str too short */
266
0
            p++, sp++;
267
0
            continue;
268
50.6M
        } else if (ch == psmp->quote_next) {
269
0
            if (++p == pend)
270
0
                return true; /* bad pattern */
271
0
            ch = *p;
272
0
        }
273
50.6M
        if (sp == spend)
274
0
            return false; /* str too short */
275
50.6M
        if (*sp == ch ||
276
50.6M
            (psmp->ignore_case && (*sp ^ ch) == 0x20 &&
277
7.42M
             (ch &= ~0x20) >= 0x41 && ch <= 0x5a) ||
278
50.6M
             (psmp->slash_equiv && ((ch == '\\' && *sp == '/') ||
279
0
             (ch == '/' && *sp == '\\')))
280
50.6M
            )
281
43.2M
            p++, sp++;
282
7.42M
        else if (pback == 0)
283
7.42M
            return false;  /* no * to back up to */
284
0
        else {
285
0
            sp = ++spback;
286
0
            p = pback;
287
0
        }
288
50.6M
    }
289
36.8k
    if (sp < spend) {   /* We got a match, but there are chars left over. */
290
        /* If we can back up, back up to the only place that */
291
        /* could produce a complete match, otherwise fail. */
292
18.4k
        if (pback == 0)
293
0
            return false;
294
18.4k
        p = pback;
295
18.4k
        pback = 0;
296
18.4k
        sp = spend - (pend - p);
297
18.4k
        goto again;
298
18.4k
    }
299
18.4k
    return true;
300
36.8k
}
301
302
/* ------ UID utilities ------ */
303
304
/* Compare two UIDs for equality. */
305
/* We know that at least one of them is valid. */
306
bool
307
uid_equal(register const gs_uid * puid1, register const gs_uid * puid2)
308
1.19M
{
309
1.19M
    if (puid1->id != puid2->id)
310
42.3k
        return false;
311
1.14M
    if (puid1->id >= 0)
312
130
        return true;    /* UniqueID */
313
1.14M
    return
314
1.14M
        !memcmp((const char *)puid1->xvalues,
315
1.14M
                (const char *)puid2->xvalues,
316
1.14M
                (uint) - (puid1->id) * sizeof(long));
317
1.14M
}
318
319
/* Copy the XUID data for a uid, if needed, updating the uid in place. */
320
int
321
uid_copy(gs_uid *puid, gs_memory_t *mem, client_name_t cname)
322
176k
{
323
176k
    if (uid_is_XUID(puid)) {
324
10.7k
        uint xsize = uid_XUID_size(puid);
325
10.7k
        long *xvalues = (long *)
326
10.7k
            gs_alloc_byte_array(mem, xsize, sizeof(long), cname);
327
328
10.7k
        if (xvalues == 0)
329
0
            return_error(gs_error_VMerror);
330
10.7k
        memcpy(xvalues, uid_XUID_values(puid), xsize * sizeof(long));
331
10.7k
        puid->xvalues = xvalues;
332
10.7k
    }
333
176k
    return 0;
334
176k
}
335
336
/* ------ Rectangle utilities ------ */
337
338
/*
339
 * Calculate the difference of two rectangles, a list of up to 4 rectangles.
340
 * Return the number of rectangles in the list, and set the first rectangle
341
 * to the intersection.
342
 */
343
int
344
int_rect_difference(gs_int_rect * outer, const gs_int_rect * inner,
345
                    gs_int_rect * diffs /*[4] */ )
346
0
{
347
0
    int x0 = outer->p.x, y0 = outer->p.y;
348
0
    int x1 = outer->q.x, y1 = outer->q.y;
349
0
    int count = 0;
350
351
0
    if (y0 < inner->p.y) {
352
0
        diffs[0].p.x = x0, diffs[0].p.y = y0;
353
0
        diffs[0].q.x = x1, diffs[0].q.y = min(y1, inner->p.y);
354
0
        outer->p.y = y0 = diffs[0].q.y;
355
0
        ++count;
356
0
    }
357
0
    if (y1 > inner->q.y) {
358
0
        diffs[count].p.x = x0, diffs[count].p.y = max(y0, inner->q.y);
359
0
        diffs[count].q.x = x1, diffs[count].q.y = y1;
360
0
        outer->q.y = y1 = diffs[count].p.y;
361
0
        ++count;
362
0
    }
363
0
    if (x0 < inner->p.x) {
364
0
        diffs[0].p.x = x0, diffs[0].p.y = y0;
365
0
        diffs[0].q.x = min(x1, inner->p.x), diffs[0].q.y = y1;
366
0
        outer->p.x = x0 = diffs[count].q.x;
367
0
        ++count;
368
0
    }
369
0
    if (x1 > inner->q.x) {
370
0
        diffs[count].p.x = max(x0, inner->q.x), diffs[count].p.y = y0;
371
0
        diffs[count].q.x = x1, diffs[count].q.y = y1;
372
0
        outer->q.x = x1 = diffs[count].p.x;
373
0
        ++count;
374
0
    }
375
0
    return count;
376
0
}