Coverage Report

Created: 2025-08-28 07:06

/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
290M
{
53
290M
    os_ptr op = osp;
54
290M
    byte *sbody;
55
290M
    uint size;
56
57
290M
    check_op(1);
58
290M
    check_type(*op, t_integer);
59
290M
    if (op->value.intval < 0 )
60
13
        return_error(gs_error_rangecheck);
61
290M
    if (op->value.intval > max_string_size )
62
12
        return_error(gs_error_limitcheck); /* to match Distiller */
63
290M
    size = op->value.intval;
64
290M
    sbody = ialloc_string(size, "string");
65
290M
    if (sbody == 0)
66
0
        return_error(gs_error_VMerror);
67
290M
    make_string(op, a_all | icurrent_space, size, sbody);
68
290M
    memset(sbody, 0, size);
69
290M
    return 0;
70
290M
}
71
72
/* <name> .namestring <string> */
73
static int
74
znamestring(i_ctx_t *i_ctx_p)
75
265M
{
76
265M
    os_ptr op = osp;
77
78
265M
    check_op(1);
79
265M
    check_type(*op, t_name);
80
265M
    name_string_ref(imemory, op, op);
81
265M
    return 0;
82
265M
}
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
4.78M
{
89
4.78M
    os_ptr op = osp;
90
4.78M
    os_ptr op1 = op - 1;
91
4.78M
    uint size = r_size(op);
92
93
4.78M
    check_op(2);
94
4.78M
    check_read_type(*op, t_string);
95
4.78M
    check_read_type(*op1, t_string);
96
4.78M
    if (size <= r_size(op1) && !memcmp(op1->value.bytes, op->value.bytes, size)) {
97
2.80M
        os_ptr op0 = op;
98
99
2.80M
        push(1);
100
2.80M
        *op0 = *op1;
101
2.80M
        r_set_size(op0, size);
102
2.80M
        op1->value.bytes += size;
103
2.80M
        r_dec_size(op1, size);
104
2.80M
        make_true(op);
105
2.80M
    } else
106
4.78M
        make_false(op);
107
4.78M
    return 0;
108
4.78M
}
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
47.6M
{
115
47.6M
    os_ptr op = osp;
116
47.6M
    os_ptr op1 = op - 1;
117
47.6M
    uint size = r_size(op);
118
47.6M
    uint count;
119
47.6M
    byte *pat;
120
47.6M
    byte *ptr;
121
47.6M
    byte ch;
122
47.6M
    int incr = forward ? 1 : -1;
123
124
47.6M
    check_op(2);
125
47.6M
    check_read_type(*op1, t_string);
126
47.6M
    check_read_type(*op, t_string);
127
47.6M
    if (size > r_size(op1)) { /* can't match */
128
8.12M
        make_false(op);
129
8.12M
        return 0;
130
8.12M
    }
131
39.5M
    count = r_size(op1) - size;
132
39.5M
    ptr = op1->value.bytes;
133
39.5M
    if (size == 0)
134
1
        goto found;
135
39.5M
    if (!forward)
136
37.7M
        ptr += count;
137
39.5M
    pat = op->value.bytes;
138
39.5M
    ch = pat[0];
139
468M
    do {
140
468M
        if (*ptr == ch && (size == 1 || !memcmp(ptr, pat, size)))
141
1.25M
            goto found;
142
467M
        ptr += incr;
143
467M
    }
144
467M
    while (count--);
145
    /* No match */
146
38.2M
    make_false(op);
147
38.2M
    return 0;
148
1.25M
found:
149
1.25M
    op->tas.type_attrs = op1->tas.type_attrs;
150
1.25M
    op->value.bytes = ptr;        /* match */
151
1.25M
    op->tas.rsize = size;       /* match */
152
1.25M
    push(2);
153
1.25M
    op[-1] = *op1;          /* pre */
154
1.25M
    op[-3].value.bytes = ptr + size;      /* post */
155
1.25M
    if (forward) {
156
874k
        op[-1].tas.rsize = ptr - op[-1].value.bytes;  /* pre */
157
874k
        op[-3].tas.rsize = count;     /* post */
158
874k
    } else {
159
379k
        op[-1].tas.rsize = count;     /* pre */
160
379k
        op[-3].tas.rsize -= count + size;   /* post */
161
379k
    }
162
1.25M
    make_true(op);
163
1.25M
    return 0;
164
1.25M
}
165
166
/* Search from the start of the string */
167
static int
168
zsearch(i_ctx_t *i_ctx_p)
169
9.94M
{
170
9.94M
    return search_impl(i_ctx_p, true);
171
9.94M
}
172
173
/* Search from the end of the string */
174
static int
175
zrsearch(i_ctx_t *i_ctx_p)
176
37.7M
{
177
37.7M
    return search_impl(i_ctx_p, false);
178
37.7M
}
179
180
/* <string> <charstring> .stringbreak <int|null> */
181
static int
182
zstringbreak(i_ctx_t *i_ctx_p)
183
93
{
184
93
    os_ptr op = osp;
185
93
    uint i, j;
186
187
93
    check_op(2);
188
93
    check_read_type(op[-1], t_string);
189
93
    check_read_type(*op, t_string);
190
    /* We can't use strpbrk here, because C doesn't allow nulls in strings. */
191
1.07k
    for (i = 0; i < r_size(op - 1); ++i)
192
17.6k
        for (j = 0; j < r_size(op); ++j)
193
16.6k
            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
93
    make_null(op - 1);
198
93
 done:
199
93
    pop(1);
200
93
    return 0;
201
93
}
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
};