Coverage Report

Created: 2025-06-10 07:27

/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
16.9M
{
53
16.9M
    os_ptr op = osp;
54
16.9M
    byte *sbody;
55
16.9M
    uint size;
56
57
16.9M
    check_op(1);
58
16.9M
    check_type(*op, t_integer);
59
16.9M
    if (op->value.intval < 0 )
60
0
        return_error(gs_error_rangecheck);
61
16.9M
    if (op->value.intval > max_string_size )
62
0
        return_error(gs_error_limitcheck); /* to match Distiller */
63
16.9M
    size = op->value.intval;
64
16.9M
    sbody = ialloc_string(size, "string");
65
16.9M
    if (sbody == 0)
66
0
        return_error(gs_error_VMerror);
67
16.9M
    make_string(op, a_all | icurrent_space, size, sbody);
68
16.9M
    memset(sbody, 0, size);
69
16.9M
    return 0;
70
16.9M
}
71
72
/* <name> .namestring <string> */
73
static int
74
znamestring(i_ctx_t *i_ctx_p)
75
15.1M
{
76
15.1M
    os_ptr op = osp;
77
78
15.1M
    check_op(1);
79
15.1M
    check_type(*op, t_name);
80
15.1M
    name_string_ref(imemory, op, op);
81
15.1M
    return 0;
82
15.1M
}
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
238k
{
89
238k
    os_ptr op = osp;
90
238k
    os_ptr op1 = op - 1;
91
238k
    uint size = r_size(op);
92
93
238k
    check_op(2);
94
238k
    check_read_type(*op, t_string);
95
238k
    check_read_type(*op1, t_string);
96
238k
    if (size <= r_size(op1) && !memcmp(op1->value.bytes, op->value.bytes, size)) {
97
225k
        os_ptr op0 = op;
98
99
225k
        push(1);
100
225k
        *op0 = *op1;
101
225k
        r_set_size(op0, size);
102
225k
        op1->value.bytes += size;
103
225k
        r_dec_size(op1, size);
104
225k
        make_true(op);
105
225k
    } else
106
238k
        make_false(op);
107
238k
    return 0;
108
238k
}
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
2.62M
{
115
2.62M
    os_ptr op = osp;
116
2.62M
    os_ptr op1 = op - 1;
117
2.62M
    uint size = r_size(op);
118
2.62M
    uint count;
119
2.62M
    byte *pat;
120
2.62M
    byte *ptr;
121
2.62M
    byte ch;
122
2.62M
    int incr = forward ? 1 : -1;
123
124
2.62M
    check_op(2);
125
2.62M
    check_read_type(*op1, t_string);
126
2.62M
    check_read_type(*op, t_string);
127
2.62M
    if (size > r_size(op1)) { /* can't match */
128
327k
        make_false(op);
129
327k
        return 0;
130
327k
    }
131
2.29M
    count = r_size(op1) - size;
132
2.29M
    ptr = op1->value.bytes;
133
2.29M
    if (size == 0)
134
0
        goto found;
135
2.29M
    if (!forward)
136
2.15M
        ptr += count;
137
2.29M
    pat = op->value.bytes;
138
2.29M
    ch = pat[0];
139
26.1M
    do {
140
26.1M
        if (*ptr == ch && (size == 1 || !memcmp(ptr, pat, size)))
141
71.1k
            goto found;
142
26.0M
        ptr += incr;
143
26.0M
    }
144
26.0M
    while (count--);
145
    /* No match */
146
2.22M
    make_false(op);
147
2.22M
    return 0;
148
71.1k
found:
149
71.1k
    op->tas.type_attrs = op1->tas.type_attrs;
150
71.1k
    op->value.bytes = ptr;        /* match */
151
71.1k
    op->tas.rsize = size;       /* match */
152
71.1k
    push(2);
153
71.1k
    op[-1] = *op1;          /* pre */
154
71.1k
    op[-3].value.bytes = ptr + size;      /* post */
155
71.1k
    if (forward) {
156
49.4k
        op[-1].tas.rsize = ptr - op[-1].value.bytes;  /* pre */
157
49.4k
        op[-3].tas.rsize = count;     /* post */
158
49.4k
    } else {
159
21.6k
        op[-1].tas.rsize = count;     /* pre */
160
21.6k
        op[-3].tas.rsize -= count + size;   /* post */
161
21.6k
    }
162
71.1k
    make_true(op);
163
71.1k
    return 0;
164
71.1k
}
165
166
/* Search from the start of the string */
167
static int
168
zsearch(i_ctx_t *i_ctx_p)
169
465k
{
170
465k
    return search_impl(i_ctx_p, true);
171
465k
}
172
173
/* Search from the end of the string */
174
static int
175
zrsearch(i_ctx_t *i_ctx_p)
176
2.15M
{
177
2.15M
    return search_impl(i_ctx_p, false);
178
2.15M
}
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
};