Coverage Report

Created: 2025-06-10 06:56

/src/ghostpdl/psi/zstring.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
/* String operators */
18
#include "memory_.h"
19
#include "ghost.h"
20
#include "gsutil.h"
21
#include "ialloc.h"
22
#include "iname.h"
23
#include "ivmspace.h"
24
#include "oper.h"
25
#include "store.h"
26
27
/* The generic operators (copy, get, put, getinterval, putinterval, */
28
/* length, and forall) are implemented in zgeneric.c. */
29
30
/* <int> .bytestring <bytestring> */
31
static int
32
zbytestring(i_ctx_t *i_ctx_p)
33
0
{
34
0
    os_ptr op = osp;
35
0
    byte *sbody;
36
0
    uint size;
37
38
0
    check_op(1);
39
0
    check_int_leu(*op, max_int);
40
0
    size = (uint)op->value.intval;
41
0
    sbody = ialloc_bytes(size, ".bytestring");
42
0
    if (sbody == 0)
43
0
        return_error(gs_error_VMerror);
44
0
    make_astruct(op, a_all | icurrent_space, sbody);
45
0
    memset(sbody, 0, size);
46
0
    return 0;
47
0
}
48
49
/* <int> string <string> */
50
int
51
zstring(i_ctx_t *i_ctx_p)
52
2.58M
{
53
2.58M
    os_ptr op = osp;
54
2.58M
    byte *sbody;
55
2.58M
    uint size;
56
57
2.58M
    check_op(1);
58
2.58M
    check_type(*op, t_integer);
59
2.58M
    if (op->value.intval < 0 )
60
0
        return_error(gs_error_rangecheck);
61
2.58M
    if (op->value.intval > max_string_size )
62
0
        return_error(gs_error_limitcheck); /* to match Distiller */
63
2.58M
    size = op->value.intval;
64
2.58M
    sbody = ialloc_string(size, "string");
65
2.58M
    if (sbody == 0)
66
0
        return_error(gs_error_VMerror);
67
2.58M
    make_string(op, a_all | icurrent_space, size, sbody);
68
2.58M
    memset(sbody, 0, size);
69
2.58M
    return 0;
70
2.58M
}
71
72
/* <name> .namestring <string> */
73
static int
74
znamestring(i_ctx_t *i_ctx_p)
75
2.49M
{
76
2.49M
    os_ptr op = osp;
77
78
2.49M
    check_op(1);
79
2.49M
    check_type(*op, t_name);
80
2.49M
    name_string_ref(imemory, op, op);
81
2.49M
    return 0;
82
2.49M
}
83
84
/* <string> <pattern> anchorsearch <post> <match> -true- */
85
/* <string> <pattern> anchorsearch <string> -false- */
86
static int
87
zanchorsearch(i_ctx_t *i_ctx_p)
88
7.69k
{
89
7.69k
    os_ptr op = osp;
90
7.69k
    os_ptr op1 = op - 1;
91
7.69k
    uint size = r_size(op);
92
93
7.69k
    check_op(2);
94
7.69k
    check_read_type(*op, t_string);
95
7.69k
    check_read_type(*op1, t_string);
96
7.69k
    if (size <= r_size(op1) && !memcmp(op1->value.bytes, op->value.bytes, size)) {
97
840
        os_ptr op0 = op;
98
99
840
        push(1);
100
840
        *op0 = *op1;
101
840
        r_set_size(op0, size);
102
840
        op1->value.bytes += size;
103
840
        r_dec_size(op1, size);
104
840
        make_true(op);
105
840
    } else
106
7.69k
        make_false(op);
107
7.69k
    return 0;
108
7.69k
}
109
110
/* <string> <pattern> (r)search <post> <match> <pre> -true- */
111
/* <string> <pattern> (r)search <string> -false- */
112
static int
113
search_impl(i_ctx_t *i_ctx_p, bool forward)
114
367k
{
115
367k
    os_ptr op = osp;
116
367k
    os_ptr op1 = op - 1;
117
367k
    uint size = r_size(op);
118
367k
    uint count;
119
367k
    byte *pat;
120
367k
    byte *ptr;
121
367k
    byte ch;
122
367k
    int incr = forward ? 1 : -1;
123
124
367k
    check_op(2);
125
367k
    check_read_type(*op1, t_string);
126
367k
    check_read_type(*op, t_string);
127
367k
    if (size > r_size(op1)) { /* can't match */
128
1.64k
        make_false(op);
129
1.64k
        return 0;
130
1.64k
    }
131
366k
    count = r_size(op1) - size;
132
366k
    ptr = op1->value.bytes;
133
366k
    if (size == 0)
134
0
        goto found;
135
366k
    if (!forward)
136
355k
        ptr += count;
137
366k
    pat = op->value.bytes;
138
366k
    ch = pat[0];
139
3.76M
    do {
140
3.76M
        if (*ptr == ch && (size == 1 || !memcmp(ptr, pat, size)))
141
12.3k
            goto found;
142
3.75M
        ptr += incr;
143
3.75M
    }
144
3.75M
    while (count--);
145
    /* No match */
146
353k
    make_false(op);
147
353k
    return 0;
148
12.3k
found:
149
12.3k
    op->tas.type_attrs = op1->tas.type_attrs;
150
12.3k
    op->value.bytes = ptr;        /* match */
151
12.3k
    op->tas.rsize = size;       /* match */
152
12.3k
    push(2);
153
12.3k
    op[-1] = *op1;          /* pre */
154
12.3k
    op[-3].value.bytes = ptr + size;      /* post */
155
12.3k
    if (forward) {
156
8.80k
        op[-1].tas.rsize = ptr - op[-1].value.bytes;  /* pre */
157
8.80k
        op[-3].tas.rsize = count;     /* post */
158
8.80k
    } else {
159
3.56k
        op[-1].tas.rsize = count;     /* pre */
160
3.56k
        op[-3].tas.rsize -= count + size;   /* post */
161
3.56k
    }
162
12.3k
    make_true(op);
163
12.3k
    return 0;
164
12.3k
}
165
166
/* Search from the start of the string */
167
static int
168
zsearch(i_ctx_t *i_ctx_p)
169
12.6k
{
170
12.6k
    return search_impl(i_ctx_p, true);
171
12.6k
}
172
173
/* Search from the end of the string */
174
static int
175
zrsearch(i_ctx_t *i_ctx_p)
176
355k
{
177
355k
    return search_impl(i_ctx_p, false);
178
355k
}
179
180
/* <string> <charstring> .stringbreak <int|null> */
181
static int
182
zstringbreak(i_ctx_t *i_ctx_p)
183
0
{
184
0
    os_ptr op = osp;
185
0
    uint i, j;
186
187
0
    check_op(2);
188
0
    check_read_type(op[-1], t_string);
189
0
    check_read_type(*op, t_string);
190
    /* We can't use strpbrk here, because C doesn't allow nulls in strings. */
191
0
    for (i = 0; i < r_size(op - 1); ++i)
192
0
        for (j = 0; j < r_size(op); ++j)
193
0
            if (op[-1].value.const_bytes[i] == op->value.const_bytes[j]) {
194
0
                make_int(op - 1, i);
195
0
                goto done;
196
0
            }
197
0
    make_null(op - 1);
198
0
 done:
199
0
    pop(1);
200
0
    return 0;
201
0
}
202
203
/* <obj> <pattern> .stringmatch <bool> */
204
static int
205
zstringmatch(i_ctx_t *i_ctx_p)
206
0
{
207
0
    os_ptr op = osp;
208
0
    os_ptr op1 = op - 1;
209
0
    bool result;
210
211
0
    check_op(2);
212
0
    check_read_type(*op, t_string);
213
0
    switch (r_type(op1)) {
214
0
        case t_string:
215
0
            check_read(*op1);
216
0
            goto cmp;
217
0
        case t_name:
218
0
            name_string_ref(imemory, op1, op1);  /* can't fail */
219
0
cmp:
220
0
            result = string_match(op1->value.const_bytes, r_size(op1),
221
0
                                  op->value.const_bytes, r_size(op),
222
0
                                  NULL);
223
0
            break;
224
0
        default:
225
0
            result = (r_size(op) == 1 && *op->value.bytes == '*');
226
0
    }
227
0
    make_bool(op1, result);
228
0
    pop(1);
229
0
    return 0;
230
0
}
231
232
/* ------ Initialization procedure ------ */
233
234
const op_def zstring_op_defs[] =
235
{
236
    {"1.bytestring", zbytestring},
237
    {"2anchorsearch", zanchorsearch},
238
    {"1.namestring", znamestring},
239
    {"2search", zsearch},
240
    {"2rsearch", zrsearch},
241
    {"1string", zstring},
242
    {"2.stringbreak", zstringbreak},
243
    {"2.stringmatch", zstringmatch},
244
    op_def_end(0)
245
};