Coverage Report

Created: 2025-06-24 07:01

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