Coverage Report

Created: 2026-04-01 07:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/base/seexec.c
Line
Count
Source
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
/* eexec filters */
18
#include "stdio_.h"   /* includes std.h */
19
#include "strimpl.h"
20
#include "sfilter.h"
21
#include "gscrypt1.h"
22
#include "scanchar.h"
23
24
/* ------ eexecEncode ------ */
25
26
/* Encoding is much simpler than decoding, because we don't */
27
/* worry about initial characters or hex vs. binary (the client */
28
/* has to take care of these aspects). */
29
30
private_st_exE_state();
31
32
/* Process a buffer */
33
static int
34
s_exE_process(stream_state * st, stream_cursor_read * pr,
35
              stream_cursor_write * pw, bool last)
36
358k
{
37
358k
    stream_exE_state *const ss = (stream_exE_state *) st;
38
358k
    const byte *p = pr->ptr;
39
358k
    byte *q = pw->ptr;
40
358k
    uint rcount = pr->limit - p;
41
358k
    uint wcount = pw->limit - q;
42
358k
    uint count;
43
358k
    int status;
44
45
358k
    if (rcount <= wcount)
46
125k
        count = rcount, status = 0;
47
232k
    else
48
232k
        count = wcount, status = 1;
49
358k
    gs_type1_encrypt(q + 1, p + 1, count, (crypt_state *)&ss->cstate);
50
358k
    pr->ptr += count;
51
358k
    pw->ptr += count;
52
358k
    return status;
53
358k
}
54
55
/* Stream template */
56
const stream_template s_exE_template = {
57
    &st_exE_state, NULL, s_exE_process, 1, 2
58
};
59
60
/* ------ eexecDecode ------ */
61
62
private_st_exD_state();
63
64
/* Set defaults. */
65
static void
66
s_exD_set_defaults(stream_state * st)
67
75.2k
{
68
75.2k
    stream_exD_state *const ss = (stream_exD_state *) st;
69
70
75.2k
    ss->binary = -1;    /* unknown */
71
75.2k
    ss->lenIV = 4;
72
75.2k
    ss->hex_left = max_long;
73
    /* Clear pointers for GC */
74
75.2k
    ss->pfb_state = 0;
75
75.2k
    ss->keep_spaces = false;    /* PS mode */
76
75.2k
    ss->is_leading_space = true;
77
75.2k
}
78
79
/* Initialize the state for reading and decrypting. */
80
/* Decrypting streams are not positionable. */
81
static int
82
s_exD_init(stream_state * st)
83
75.2k
{
84
75.2k
    stream_exD_state *const ss = (stream_exD_state *) st;
85
86
75.2k
    ss->odd = -1;
87
75.2k
    ss->skip = ss->lenIV;
88
75.2k
    return 0;
89
75.2k
}
90
91
/* Process a buffer. */
92
static int
93
s_exD_process(stream_state * st, stream_cursor_read * pr,
94
              stream_cursor_write * pw, bool last)
95
93.1M
{
96
93.1M
    stream_exD_state *const ss = (stream_exD_state *) st;
97
93.1M
    const byte *p = pr->ptr;
98
93.1M
    byte *q = pw->ptr;
99
93.1M
    int skip = ss->skip;
100
93.1M
    int rcount = pr->limit - p;
101
93.1M
    int wcount = pw->limit - q;
102
93.1M
    int status = 0;
103
93.1M
    int count = (wcount < rcount ? (status = 1, wcount) : rcount);
104
105
93.1M
    if (ss->binary < 0) {
106
        /*
107
         * This is the very first time we're filling the buffer.
108
         */
109
75.2k
        const byte *const decoder = scan_char_decoder;
110
75.2k
        int i;
111
112
75.2k
        if (ss->pfb_state == 0 && !ss->keep_spaces) {
113
            /*
114
             * Skip '\t', '\r', '\n', ' ' at the beginning of the input stream,
115
             * because Adobe PS interpreters do this. Don't skip '\0' or '\f'.
116
             * Acrobat Reader doesn't skip spaces at all.
117
             */
118
15.8k
            for (; rcount; rcount--, p++) {
119
15.8k
                byte c = p[1];
120
15.8k
                if(c != '\t' && c != char_CR && c != char_EOL && c != ' ')
121
15.8k
                    break;
122
15.8k
            }
123
15.8k
            pr->ptr = p;
124
15.8k
            count = min(wcount, rcount);
125
15.8k
        }
126
127
        /*
128
         * Determine whether this is ASCII or hex encoding.
129
         * Adobe's documentation doesn't actually specify the test
130
         * that eexec should use, but we believe the following
131
         * gives correct answers even on certain non-conforming
132
         * PostScript files encountered in practice:
133
         */
134
75.2k
        if (rcount < 8 && !last)
135
0
            return 0;
136
137
75.2k
        ss->binary = 0;
138
80.7k
        for (i = min(8, rcount); i > 0; i--)
139
80.0k
            if (!(decoder[p[i]] <= 0xf ||
140
74.6k
                  decoder[p[i]] == ctype_space)
141
80.0k
                ) {
142
74.5k
                ss->binary = 1;
143
74.5k
                break;
144
74.5k
            }
145
75.2k
    }
146
93.1M
    if (ss->binary) {
147
        /*
148
         * There is no need to pause at the end of the binary portion.
149
         * The padding bytes (which are in the text portion, in hexadecimal)
150
         * do their job, provided the write buffer is <= 256 bytes long.
151
         * This is (hopefully) ensured by the comment just above the
152
         * definition of s_exD_template.
153
         */
154
93.0M
        pr->ptr = p + count;
155
93.0M
    } else {
156
        /*
157
         * We only ignore leading whitespace, in an attempt to
158
         * keep from reading beyond the end of the encrypted data;
159
         * but some badly coded files require us to ignore % also.
160
         */
161
112k
        stream_cursor_read r;
162
112k
        const byte *start;
163
164
112k
hp: r = *pr;
165
112k
        start = r.ptr;
166
112k
        if (r.limit - r.ptr > ss->hex_left)
167
0
            r.limit = r.ptr + ss->hex_left;
168
112k
        status = s_hex_process(&r, pw, &ss->odd,
169
112k
          (ss->is_leading_space ? hex_ignore_leading_whitespace : hex_break_on_whitespace));
170
112k
        if (status == 2) {
171
47.1k
            ss->is_leading_space = true;
172
47.1k
            status = 1;
173
47.1k
        } else
174
65.3k
            ss->is_leading_space = false;
175
112k
        pr->ptr = r.ptr;
176
112k
        ss->hex_left -= r.ptr - start;
177
        /*
178
         * Check for having finished a prematurely decoded hex section of
179
         * a PFB file.
180
         */
181
112k
        if (ss->hex_left == 0)
182
0
            ss->binary = 1;
183
112k
        count = pw->ptr - q;
184
112k
        if (status < 0 && ss->odd < 0) {
185
15.6k
            if (count) {
186
7.70k
                --p;
187
7.70k
                status = 0; /* reprocess error next time */
188
7.99k
            } else if (p > pr->ptr && p < pr->limit && *p == '%')
189
0
                goto hp; /* ignore % */
190
15.6k
        }
191
112k
        p = q;
192
112k
    }
193
93.1M
    if (skip >= count && skip != 0) {
194
37
        gs_type1_decrypt(q + 1, p + 1, count,
195
37
                         (crypt_state *) & ss->cstate);
196
37
        ss->skip -= count;
197
37
        count = 0;
198
37
        status = 0;
199
93.1M
    } else {
200
93.1M
        gs_type1_decrypt(q + 1, p + 1, skip,
201
93.1M
                         (crypt_state *) & ss->cstate);
202
93.1M
        count -= skip;
203
93.1M
        gs_type1_decrypt(q + 1, p + 1 + skip, count,
204
93.1M
                         (crypt_state *) & ss->cstate);
205
93.1M
        ss->skip = 0;
206
93.1M
    }
207
93.1M
    pw->ptr = q + count;
208
93.1M
    return status;
209
93.1M
}
210
211
/* Stream template */
212
/*
213
 * The specification of eexec decoding requires that it never read more than
214
 * 512 source bytes ahead.  The only reliable way to ensure this is to
215
 * limit the size of the output buffer to 256.  We set it a little smaller
216
 * so that it will stay under the limit even after adding min_in_size
217
 * for a subsequent filter in a pipeline.  Note that we have to specify
218
 * a size of at least 128 so that filter_read won't round it up.
219
 * The value of 132 is samll enough for the sample file of the bug 689577 but
220
 * still sufficient for comparefiles/fonttest.pdf .
221
 */
222
const stream_template s_exD_template = {
223
    &st_exD_state, s_exD_init, s_exD_process, 8, 132,
224
    NULL, s_exD_set_defaults
225
};