Coverage Report

Created: 2025-06-10 07:27

/src/ghostpdl/base/seexec.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
/* 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
495k
{
37
495k
    stream_exE_state *const ss = (stream_exE_state *) st;
38
495k
    const byte *p = pr->ptr;
39
495k
    byte *q = pw->ptr;
40
495k
    uint rcount = pr->limit - p;
41
495k
    uint wcount = pw->limit - q;
42
495k
    uint count;
43
495k
    int status;
44
45
495k
    if (rcount <= wcount)
46
172k
        count = rcount, status = 0;
47
322k
    else
48
322k
        count = wcount, status = 1;
49
495k
    gs_type1_encrypt(q + 1, p + 1, count, (crypt_state *)&ss->cstate);
50
495k
    pr->ptr += count;
51
495k
    pw->ptr += count;
52
495k
    return status;
53
495k
}
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
77.4k
{
68
77.4k
    stream_exD_state *const ss = (stream_exD_state *) st;
69
70
77.4k
    ss->binary = -1;    /* unknown */
71
77.4k
    ss->lenIV = 4;
72
77.4k
    ss->hex_left = max_long;
73
    /* Clear pointers for GC */
74
77.4k
    ss->pfb_state = 0;
75
77.4k
    ss->keep_spaces = false;    /* PS mode */
76
77.4k
    ss->is_leading_space = true;
77
77.4k
}
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
77.4k
{
84
77.4k
    stream_exD_state *const ss = (stream_exD_state *) st;
85
86
77.4k
    ss->odd = -1;
87
77.4k
    ss->skip = ss->lenIV;
88
77.4k
    return 0;
89
77.4k
}
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
90.8M
{
96
90.8M
    stream_exD_state *const ss = (stream_exD_state *) st;
97
90.8M
    const byte *p = pr->ptr;
98
90.8M
    byte *q = pw->ptr;
99
90.8M
    int skip = ss->skip;
100
90.8M
    int rcount = pr->limit - p;
101
90.8M
    int wcount = pw->limit - q;
102
90.8M
    int status = 0;
103
90.8M
    int count = (wcount < rcount ? (status = 1, wcount) : rcount);
104
105
90.8M
    if (ss->binary < 0) {
106
        /*
107
         * This is the very first time we're filling the buffer.
108
         */
109
77.4k
        const byte *const decoder = scan_char_decoder;
110
77.4k
        int i;
111
112
77.4k
        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
13.7k
            for (; rcount; rcount--, p++) {
119
13.7k
                byte c = p[1];
120
13.7k
                if(c != '\t' && c != char_CR && c != char_EOL && c != ' ')
121
13.6k
                    break;
122
13.7k
            }
123
13.7k
            pr->ptr = p;
124
13.7k
            count = min(wcount, rcount);
125
13.7k
        }
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
77.4k
        if (rcount < 8 && !last)
135
4
            return 0;
136
137
77.4k
        ss->binary = 0;
138
82.1k
        for (i = min(8, rcount); i > 0; i--)
139
81.5k
            if (!(decoder[p[i]] <= 0xf ||
140
81.5k
                  decoder[p[i]] == ctype_space)
141
81.5k
                ) {
142
76.8k
                ss->binary = 1;
143
76.8k
                break;
144
76.8k
            }
145
77.4k
    }
146
90.8M
    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
90.7M
        pr->ptr = p + count;
155
90.7M
    } 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
101k
        stream_cursor_read r;
162
101k
        const byte *start;
163
164
101k
hp: r = *pr;
165
101k
        start = r.ptr;
166
101k
        if (r.limit - r.ptr > ss->hex_left)
167
0
            r.limit = r.ptr + ss->hex_left;
168
101k
        status = s_hex_process(&r, pw, &ss->odd,
169
101k
          (ss->is_leading_space ? hex_ignore_leading_whitespace : hex_break_on_whitespace));
170
101k
        if (status == 2) {
171
44.6k
            ss->is_leading_space = true;
172
44.6k
            status = 1;
173
44.6k
        } else
174
57.1k
            ss->is_leading_space = false;
175
101k
        pr->ptr = r.ptr;
176
101k
        ss->hex_left -= r.ptr - start;
177
        /*
178
         * Check for having finished a prematurely decoded hex section of
179
         * a PFB file.
180
         */
181
101k
        if (ss->hex_left == 0)
182
0
            ss->binary = 1;
183
101k
        count = pw->ptr - q;
184
101k
        if (status < 0 && ss->odd < 0) {
185
13.3k
            if (count) {
186
6.52k
                --p;
187
6.52k
                status = 0; /* reprocess error next time */
188
6.83k
            } else if (p > pr->ptr && p < pr->limit && *p == '%')
189
0
                goto hp; /* ignore % */
190
13.3k
        }
191
101k
        p = q;
192
101k
    }
193
90.8M
    if (skip >= count && skip != 0) {
194
34
        gs_type1_decrypt(q + 1, p + 1, count,
195
34
                         (crypt_state *) & ss->cstate);
196
34
        ss->skip -= count;
197
34
        count = 0;
198
34
        status = 0;
199
90.8M
    } else {
200
90.8M
        gs_type1_decrypt(q + 1, p + 1, skip,
201
90.8M
                         (crypt_state *) & ss->cstate);
202
90.8M
        count -= skip;
203
90.8M
        gs_type1_decrypt(q + 1, p + 1 + skip, count,
204
90.8M
                         (crypt_state *) & ss->cstate);
205
90.8M
        ss->skip = 0;
206
90.8M
    }
207
90.8M
    pw->ptr = q + count;
208
90.8M
    return status;
209
90.8M
}
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
};