Coverage Report

Created: 2025-06-10 07:17

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