/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 | | }; |