Coverage Report

Created: 2025-06-24 07:01

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