/src/ghostpdl/psi/iscan.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2022 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., 1305 Grant Avenue - Suite 200, Novato, |
13 | | CA 94945, U.S.A., +1(415)492-9861, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* Token scanner for Ghostscript interpreter */ |
18 | | #include "ghost.h" |
19 | | #include "memory_.h" |
20 | | #include "string_.h" |
21 | | #include "stream.h" |
22 | | #include "ierrors.h" |
23 | | #include "btoken.h" /* for ref_binary_object_format */ |
24 | | #include "files.h" /* for fptr */ |
25 | | #include "ialloc.h" |
26 | | #include "idict.h" /* for //name lookup */ |
27 | | #include "dstack.h" /* ditto */ |
28 | | #include "ilevel.h" |
29 | | #include "iname.h" |
30 | | #include "ipacked.h" |
31 | | #include "iparray.h" |
32 | | #include "strimpl.h" /* for string decoding */ |
33 | | #include "sa85d.h" /* ditto */ |
34 | | #include "sfilter.h" /* ditto */ |
35 | | #include "ostack.h" /* for accumulating proc bodies; */ |
36 | | /* must precede iscan.h */ |
37 | | #include "iscan.h" /* defines interface */ |
38 | | #include "iscanbin.h" |
39 | | #include "iscannum.h" |
40 | | #include "istream.h" |
41 | | #include "istruct.h" /* for RELOC_REF_VAR */ |
42 | | #include "iutil.h" |
43 | | #include "ivmspace.h" |
44 | | #include "store.h" |
45 | | #include "scanchar.h" |
46 | | |
47 | | /* |
48 | | * Level 2 includes some changes in the scanner: |
49 | | * - \ is always recognized in strings, regardless of the data source; |
50 | | * - << and >> are legal tokens; |
51 | | * - <~ introduces an ASCII85 encoded string (terminated by ~>); |
52 | | * - Character codes above 127 introduce binary objects. |
53 | | * We explicitly enable or disable these changes based on level2_enabled. |
54 | | */ |
55 | | |
56 | | /* ------ Dynamic strings ------ */ |
57 | | |
58 | | /* Begin collecting a dynamically allocated string. */ |
59 | | static inline void |
60 | | dynamic_init(da_ptr pda, gs_memory_t *mem) |
61 | 171M | { |
62 | 171M | pda->is_dynamic = false; |
63 | 171M | pda->limit = pda->buf + sizeof(pda->buf); |
64 | 171M | pda->next = pda->base = pda->buf; |
65 | 171M | pda->memory = mem; |
66 | 171M | } |
67 | | |
68 | | /* Free a dynamic string. */ |
69 | | static void |
70 | | dynamic_free(da_ptr pda) |
71 | 788M | { |
72 | 788M | if (pda->is_dynamic) |
73 | 6.44M | gs_free_string(pda->memory, pda->base, da_size(pda), "scanner"); |
74 | 788M | } |
75 | | |
76 | | /* Resize a dynamic string. */ |
77 | | /* If the allocation fails, return gs_error_VMerror; otherwise, return 0. */ |
78 | | static int |
79 | | dynamic_resize(da_ptr pda, uint new_size) |
80 | 178M | { |
81 | 178M | uint old_size = da_size(pda); |
82 | 178M | uint pos = pda->next - pda->base; |
83 | 178M | gs_memory_t *mem = pda->memory; |
84 | 178M | byte *base; |
85 | | |
86 | 178M | if (pda->is_dynamic) { |
87 | 454k | base = gs_resize_string(mem, pda->base, old_size, |
88 | 454k | new_size, "scanner"); |
89 | 454k | if (base == 0) |
90 | 0 | return_error(gs_error_VMerror); |
91 | 178M | } else { /* switching from static to dynamic */ |
92 | 178M | base = gs_alloc_string(mem, new_size, "scanner"); |
93 | 178M | if (base == 0) |
94 | 0 | return_error(gs_error_VMerror); |
95 | 178M | memcpy(base, pda->base, min(old_size, new_size)); |
96 | 178M | pda->is_dynamic = true; |
97 | 178M | } |
98 | 178M | pda->base = base; |
99 | 178M | pda->next = base + pos; |
100 | 178M | pda->limit = base + new_size; |
101 | 178M | return 0; |
102 | 178M | } |
103 | | |
104 | | /* Grow a dynamic string. */ |
105 | | /* Return 0 if the allocation failed, the new 'next' ptr if OK. */ |
106 | | /* Return 0 or an error code, updating pda->next to point to the first */ |
107 | | /* available byte after growing. */ |
108 | | static int |
109 | | dynamic_grow(da_ptr pda, byte * next, uint max_size) |
110 | 6.90M | { |
111 | 6.90M | uint old_size = da_size(pda); |
112 | 6.90M | uint new_size = (old_size < 10 ? 20 : |
113 | 6.90M | old_size >= (max_size >> 1) ? max_size : |
114 | 1.77M | old_size << 1); |
115 | 6.90M | int code; |
116 | | |
117 | 6.90M | pda->next = next; |
118 | 6.90M | if (old_size >= max_size) |
119 | 101 | return_error(gs_error_limitcheck); |
120 | 6.90M | while ((code = dynamic_resize(pda, new_size)) < 0) { |
121 | | /* Try trimming down the requested new size. */ |
122 | 0 | new_size -= (new_size - old_size + 1) >> 1; |
123 | 0 | if (new_size <= old_size) |
124 | 0 | break; |
125 | 0 | } |
126 | 6.90M | return code; |
127 | 6.90M | } |
128 | | |
129 | | /* Ensure that a dynamic string is either on the heap or in the */ |
130 | | /* private buffer. */ |
131 | | static void |
132 | | dynamic_save(da_ptr pda) |
133 | 357k | { |
134 | 357k | if (!pda->is_dynamic && pda->base != pda->buf) { |
135 | 34 | int len = da_size(pda); |
136 | | |
137 | 34 | if (len > sizeof(pda->buf)) |
138 | 1 | len = sizeof(pda->buf); |
139 | 34 | memcpy(pda->buf, pda->base, len); |
140 | 34 | pda->next = pda->buf + len; |
141 | 34 | pda->base = pda->buf; |
142 | 34 | } |
143 | 357k | } |
144 | | |
145 | | /* Finish collecting a dynamic string. */ |
146 | | static int |
147 | | dynamic_make_string(i_ctx_t *i_ctx_p, ref * pref, da_ptr pda, byte * next) |
148 | 171M | { |
149 | 171M | uint size = (pda->next = next) - pda->base; |
150 | 171M | int code = dynamic_resize(pda, size); |
151 | | |
152 | 171M | if (code < 0) |
153 | 0 | return code; |
154 | 171M | make_tasv_new(pref, t_string, |
155 | 171M | a_all | imemory_space((gs_ref_memory_t *) pda->memory), |
156 | 171M | size, bytes, pda->base); |
157 | 171M | return 0; |
158 | 171M | } |
159 | | |
160 | | /* ------ Main scanner ------ */ |
161 | | |
162 | | /* GC procedures */ |
163 | | static |
164 | | CLEAR_MARKS_PROC(scanner_clear_marks) |
165 | 287 | { |
166 | 287 | scanner_state *const ssptr = vptr; |
167 | | |
168 | 287 | r_clear_attrs(&ssptr->s_file, l_mark); |
169 | 287 | r_clear_attrs(&ssptr->s_ss.binary.bin_array, l_mark); |
170 | 287 | r_clear_attrs(&ssptr->s_error.object, l_mark); |
171 | 287 | } |
172 | | static |
173 | 1.04k | ENUM_PTRS_WITH(scanner_enum_ptrs, scanner_state *ssptr) return 0; |
174 | 261 | case 0: |
175 | 261 | ENUM_RETURN_REF(&ssptr->s_file); |
176 | 261 | case 1: |
177 | 261 | ENUM_RETURN_REF(&ssptr->s_error.object); |
178 | 261 | case 2: |
179 | 261 | if (ssptr->s_scan_type == scanning_none || |
180 | 261 | !ssptr->s_da.is_dynamic |
181 | 261 | ) |
182 | 248 | ENUM_RETURN(0); |
183 | 13 | return ENUM_STRING2(ssptr->s_da.base, da_size(&ssptr->s_da)); |
184 | 261 | case 3: |
185 | 261 | if (ssptr->s_scan_type != scanning_binary) |
186 | 261 | return 0; |
187 | 1.04k | ENUM_RETURN_REF(&ssptr->s_ss.binary.bin_array); |
188 | 1.04k | ENUM_PTRS_END |
189 | 261 | static RELOC_PTRS_WITH(scanner_reloc_ptrs, scanner_state *ssptr) |
190 | 261 | { |
191 | 261 | RELOC_REF_VAR(ssptr->s_file); |
192 | 261 | r_clear_attrs(&ssptr->s_file, l_mark); |
193 | 261 | if (ssptr->s_scan_type != scanning_none && ssptr->s_da.is_dynamic) { |
194 | 13 | gs_string sda; |
195 | | |
196 | 13 | sda.data = ssptr->s_da.base; |
197 | 13 | sda.size = da_size(&ssptr->s_da); |
198 | 13 | RELOC_STRING_VAR(sda); |
199 | 13 | ssptr->s_da.limit = sda.data + sda.size; |
200 | 13 | ssptr->s_da.next = sda.data + (ssptr->s_da.next - ssptr->s_da.base); |
201 | 13 | ssptr->s_da.base = sda.data; |
202 | 13 | } |
203 | 261 | if (ssptr->s_scan_type == scanning_binary) { |
204 | 0 | RELOC_REF_VAR(ssptr->s_ss.binary.bin_array); |
205 | 0 | r_clear_attrs(&ssptr->s_ss.binary.bin_array, l_mark); |
206 | 0 | } |
207 | 261 | RELOC_REF_VAR(ssptr->s_error.object); |
208 | 261 | r_clear_attrs(&ssptr->s_error.object, l_mark); |
209 | 261 | } |
210 | 261 | RELOC_PTRS_END |
211 | | /* Structure type */ |
212 | | public_st_scanner_state_dynamic(); |
213 | | |
214 | | /* Initialize a scanner. */ |
215 | | void |
216 | | gs_scanner_init_options(scanner_state *sstate, const ref *fop, int options) |
217 | 3.89G | { |
218 | 3.89G | ref_assign(&sstate->s_file, fop); |
219 | 3.89G | sstate->s_scan_type = scanning_none; |
220 | 3.89G | sstate->s_pstack = 0; |
221 | 3.89G | sstate->s_options = options; |
222 | 3.89G | SCAN_INIT_ERROR(sstate); |
223 | 3.89G | } |
224 | | void gs_scanner_init_stream_options(scanner_state *sstate, stream *s, |
225 | | int options) |
226 | 1.70M | { |
227 | | /* |
228 | | * The file 'object' will never be accessed, but it must be in correct |
229 | | * form for the GC. |
230 | | */ |
231 | 1.70M | ref fobj; |
232 | | |
233 | 1.70M | make_file(&fobj, a_read, 0, s); |
234 | 1.70M | gs_scanner_init_options(sstate, &fobj, options); |
235 | 1.70M | } |
236 | | |
237 | | /* |
238 | | * Return the "error object" to be stored in $error.command instead of |
239 | | * --token--, if any, or <0 if no special error object is available. |
240 | | */ |
241 | | int |
242 | | gs_scanner_error_object(i_ctx_t *i_ctx_p, const scanner_state *pstate, |
243 | | ref *pseo) |
244 | 16.5k | { |
245 | 16.5k | if (!r_has_type(&pstate->s_error.object, t__invalid)) { |
246 | 132 | ref_assign(pseo, &pstate->s_error.object); |
247 | 132 | return 0; |
248 | 132 | } |
249 | 16.4k | if (pstate->s_error.string[0]) { |
250 | 5.47k | int len = strlen(pstate->s_error.string); |
251 | | |
252 | 5.47k | if (pstate->s_error.is_name) { |
253 | 166 | int code = name_ref(imemory, (const byte *)pstate->s_error.string, len, pseo, 1); |
254 | | |
255 | 166 | if (code < 0) |
256 | 0 | return code; |
257 | 166 | r_set_attrs(pseo, a_executable); /* Adobe compatibility */ |
258 | 166 | return 0; |
259 | 5.30k | } else { |
260 | 5.30k | byte *estr = ialloc_string(len, "gs_scanner_error_object"); |
261 | | |
262 | 5.30k | if (estr == 0) |
263 | 0 | return -1; /* VMerror */ |
264 | 5.30k | memcpy(estr, (const byte *)pstate->s_error.string, len); |
265 | 5.30k | make_string(pseo, a_all | icurrent_space, len, estr); |
266 | 5.30k | return 0; |
267 | 5.30k | } |
268 | 5.47k | } |
269 | 10.9k | return -1; /* no error object */ |
270 | 16.4k | } |
271 | | |
272 | | /* Handle a scan_Refill return from gs_scan_token. */ |
273 | | /* This may return o_push_estack, 0 (meaning just call gs_scan_token */ |
274 | | /* again), or an error code. */ |
275 | | int |
276 | | gs_scan_handle_refill(i_ctx_t *i_ctx_p, scanner_state * sstate, |
277 | | bool save, op_proc_t cont) |
278 | 1.05M | { |
279 | 1.05M | const ref *const fop = &sstate->s_file; |
280 | 1.05M | stream *s = fptr(fop); |
281 | 1.05M | uint avail = sbufavailable(s); |
282 | 1.05M | int status; |
283 | | |
284 | 1.05M | if (s->end_status == EOFC) { |
285 | | /* More data needed, but none available, so this is a syntax error. */ |
286 | 999 | return_error(gs_error_syntaxerror); |
287 | 999 | } |
288 | 1.05M | status = s_process_read_buf(s); |
289 | 1.05M | if (sbufavailable(s) > avail) |
290 | 251k | return 0; |
291 | 804k | if (status == 0) |
292 | 804k | status = s->end_status; |
293 | 804k | switch (status) { |
294 | 1.01k | case EOFC: |
295 | | /* We just discovered that we're at EOF. */ |
296 | | /* Let the caller find this out. */ |
297 | 1.01k | return 0; |
298 | 3 | case ERRC: |
299 | 3 | return_error(gs_error_ioerror); |
300 | 0 | case INTC: |
301 | 803k | case CALLC: |
302 | 803k | { |
303 | 803k | ref rstate[1]; |
304 | 803k | scanner_state *pstate; |
305 | | |
306 | 803k | if (save) { |
307 | 713k | pstate = (scanner_state *) |
308 | 713k | ialloc_struct(scanner_state_dynamic, &st_scanner_state_dynamic, |
309 | 713k | "gs_scan_handle_refill"); |
310 | 713k | if (pstate == 0) |
311 | 0 | return_error(gs_error_VMerror); |
312 | 713k | ((scanner_state_dynamic *)pstate)->mem = imemory; |
313 | 713k | *pstate = *sstate; |
314 | 713k | } else |
315 | 89.2k | pstate = sstate; |
316 | 803k | make_istruct(&rstate[0], 0, pstate); |
317 | 803k | return s_handle_read_exception(i_ctx_p, status, fop, |
318 | 803k | rstate, 1, cont); |
319 | 803k | } |
320 | 804k | } |
321 | | /* No more data available, but no exception. */ |
322 | | /* A filter is consuming headers but returns nothing. */ |
323 | 261 | return 0; |
324 | 804k | } |
325 | | |
326 | | /* |
327 | | * Handle a comment. The 'saved' argument is needed only for |
328 | | * tracing printout. |
329 | | */ |
330 | | static int |
331 | | scan_comment(i_ctx_t *i_ctx_p, ref *pref, scanner_state *pstate, |
332 | | const byte * base, const byte * end, bool saved) |
333 | 2.51M | { |
334 | 2.51M | uint len = (uint) (end - base); |
335 | 2.51M | int code; |
336 | | #ifdef DEBUG |
337 | | const char *sstr = (saved ? ">" : ""); |
338 | | #endif |
339 | | |
340 | 2.51M | if (len > 1 && (base[1] == '%' || base[1] == '!')) { |
341 | | /* Process as a DSC comment if requested. */ |
342 | | #ifdef DEBUG |
343 | | if (gs_debug_c('%')) { |
344 | | dmlprintf2(imemory, "[%%%%%s%c]", sstr, (len >= 3 ? '+' : '-')); |
345 | | debug_print_string(imemory, base, len); |
346 | | dmputs(imemory, "\n"); |
347 | | } |
348 | | #endif |
349 | 1.12M | if (pstate->s_options & SCAN_PROCESS_DSC_COMMENTS) { |
350 | 1.10M | code = scan_DSC_Comment; |
351 | 1.10M | goto comment; |
352 | 1.10M | } |
353 | | /* Treat as an ordinary comment. */ |
354 | 1.12M | } |
355 | | #ifdef DEBUG |
356 | | else { |
357 | | if (gs_debug_c('%')) { |
358 | | dmlprintf2(imemory, "[%% %s%c]", sstr, (len >= 2 ? '+' : '-')); |
359 | | debug_print_string(imemory, base, len); |
360 | | dmputs(imemory, "\n"); |
361 | | } |
362 | | } |
363 | | #endif |
364 | 1.41M | if (pstate->s_options & SCAN_PROCESS_COMMENTS) { |
365 | 0 | code = scan_Comment; |
366 | 0 | goto comment; |
367 | 0 | } |
368 | 1.41M | return 0; |
369 | 1.10M | comment: |
370 | 1.10M | { |
371 | 1.10M | byte *cstr = ialloc_string(len, "scan_comment"); |
372 | | |
373 | 1.10M | if (cstr == 0) |
374 | 0 | return_error(gs_error_VMerror); |
375 | 1.10M | memcpy(cstr, base, len); |
376 | 1.10M | make_string(pref, a_all | icurrent_space, len, cstr); |
377 | 1.10M | } |
378 | 0 | return code; |
379 | 1.10M | } |
380 | | |
381 | | /* Read a token from a string. */ |
382 | | /* Update the string if succesful. */ |
383 | | /* Store the error object in i_ctx_p->error_object if not. */ |
384 | | int |
385 | | gs_scan_string_token_options(i_ctx_t *i_ctx_p, ref * pstr, ref * pref, |
386 | | int options) |
387 | 1.26M | { |
388 | 1.26M | stream st; |
389 | 1.26M | stream *s = &st; |
390 | 1.26M | scanner_state state; |
391 | 1.26M | int code; |
392 | | |
393 | 1.26M | if (!r_has_attr(pstr, a_read)) |
394 | 0 | return_error(gs_error_invalidaccess); |
395 | 1.26M | s_init(s, NULL); |
396 | 1.26M | sread_string(s, pstr->value.bytes, r_size(pstr)); |
397 | 1.26M | gs_scanner_init_stream_options(&state, s, options | SCAN_FROM_STRING); |
398 | 1.26M | switch (code = gs_scan_token(i_ctx_p, pref, &state)) { |
399 | 12 | default: /* error or comment */ |
400 | 12 | if (code < 0) |
401 | 12 | break; |
402 | | /* falls through */ |
403 | 1.26M | case 0: /* read a token */ |
404 | 1.26M | case scan_BOS: |
405 | 1.26M | { |
406 | 1.26M | uint pos = stell(s); |
407 | | |
408 | 1.26M | pstr->value.bytes += pos; |
409 | 1.26M | r_dec_size(pstr, pos); |
410 | 1.26M | } |
411 | 1.26M | break; |
412 | 1 | case scan_Refill: /* error */ |
413 | 1 | code = gs_note_error(gs_error_syntaxerror); |
414 | 136 | case scan_EOF: |
415 | 136 | break; |
416 | 1.26M | } |
417 | 1.26M | if (code < 0) |
418 | 13 | gs_scanner_error_object(i_ctx_p, &state, &i_ctx_p->error_object); |
419 | 1.26M | return code; |
420 | 1.26M | } |
421 | | |
422 | | /* |
423 | | * Read a token from a stream. Return 0 if an ordinary token was read, |
424 | | * >0 for special situations (see iscan.h). |
425 | | * If the token required a terminating character (i.e., was a name or |
426 | | * number) and the next character was whitespace, read and discard |
427 | | * that character. Note that the state is relevant for gs_error_VMerror |
428 | | * as well as for scan_Refill. |
429 | | */ |
430 | | int |
431 | | gs_scan_token(i_ctx_t *i_ctx_p, ref * pref, scanner_state * pstate) /* lgtm [cpp/use-of-goto] */ |
432 | 3.90G | { |
433 | 3.90G | stream *const s = pstate->s_file.value.pfile; |
434 | 3.90G | ref *myref = pref; |
435 | 3.90G | int retcode = 0; |
436 | 3.90G | int c; |
437 | | |
438 | 3.90G | s_declare_inline(s, sptr, endptr); |
439 | 3.90G | const byte *newptr; |
440 | 3.90G | byte *daptr; |
441 | | |
442 | 3.90G | #define sreturn(code)\ |
443 | 3.90G | { retcode = gs_note_error(code); goto sret; } |
444 | 3.90G | #define if_not_spush1()\ |
445 | 7.34G | if ( osp < ostop ) osp++;\ |
446 | 7.34G | else if ( (retcode = ref_stack_push(&o_stack, 1)) >= 0 )\ |
447 | 43.2k | ;\ |
448 | 43.2k | else |
449 | 3.90G | #define spop1()\ |
450 | 3.90G | if ( osp >= osbot ) osp--;\ |
451 | 191M | else ref_stack_pop(&o_stack, 1) |
452 | 3.90G | int max_name_ctype = |
453 | 3.90G | ((ref_binary_object_format.value.intval != 0 && level2_enabled)? ctype_name : ctype_btoken); |
454 | | |
455 | 3.90G | #define scan_sign(sign, ptr)\ |
456 | 3.90G | switch ( *ptr ) {\ |
457 | 3.34M | case '-': sign = -1; ptr++; break;\ |
458 | 5.12k | case '+': sign = 1; ptr++; break;\ |
459 | 1.05G | default: sign = 0;\ |
460 | 1.05G | } |
461 | 3.90G | #define refill2_back(styp,nback)\ |
462 | 3.90G | BEGIN sptr -= nback; sstate.s_scan_type = styp; goto pause; END |
463 | 3.90G | #define ensure2_back(styp,nback)\ |
464 | 3.90G | if ( sptr >= endptr ) refill2_back(styp,nback) |
465 | 3.90G | #define ensure2(styp) ensure2_back(styp, 1) |
466 | 3.90G | #define refill2(styp) refill2_back(styp, 1) |
467 | 3.90G | byte s1[2]; |
468 | 3.90G | const byte *const decoder = scan_char_decoder; |
469 | 3.90G | int status; |
470 | 3.90G | int sign; |
471 | 3.90G | const bool check_only = (pstate->s_options & SCAN_CHECK_ONLY) != 0; |
472 | 3.90G | const bool PDFScanRules = (i_ctx_p->scanner_options & SCAN_PDF_RULES) != 0; |
473 | | /* |
474 | | * The following is a hack so that ^D will be self-delimiting in PS files |
475 | | * (to compensate for bugs in some PostScript-generating applications) |
476 | | * but not in strings (to match CPSI on the CET) or PDF. |
477 | | */ |
478 | 3.90G | const int ctrld = (pstate->s_options & SCAN_FROM_STRING || |
479 | 3.90G | PDFScanRules ? 0x04 : 0xffff); |
480 | 3.90G | scanner_state sstate; |
481 | | |
482 | 3.90G | sptr = endptr = NULL; /* Quiet compiler */ |
483 | 3.90G | if (pstate->s_pstack != 0) { |
484 | 267k | if_not_spush1() |
485 | 0 | return retcode; |
486 | 267k | myref = osp; |
487 | 267k | } |
488 | | /* Check whether we are resuming after an interruption. */ |
489 | 3.90G | if (pstate->s_scan_type != scanning_none) { |
490 | 367k | sstate = *pstate; |
491 | 367k | if (!sstate.s_da.is_dynamic && sstate.s_da.base != sstate.s_da.buf) { |
492 | | /* The sstate.s_da contains some self-referencing pointers. */ |
493 | | /* Fix them up now. */ |
494 | 529 | uint next = sstate.s_da.next - sstate.s_da.base; |
495 | 529 | uint limit = sstate.s_da.limit - sstate.s_da.base; |
496 | | |
497 | 529 | sstate.s_da.base = sstate.s_da.buf; |
498 | 529 | sstate.s_da.next = sstate.s_da.buf + next; |
499 | 529 | sstate.s_da.limit = sstate.s_da.buf + limit; |
500 | 529 | } |
501 | 367k | daptr = sstate.s_da.next; |
502 | 367k | switch (sstate.s_scan_type) { |
503 | 10.1k | case scanning_binary: |
504 | 10.1k | retcode = (*sstate.s_ss.binary.cont) |
505 | 10.1k | (i_ctx_p, myref, &sstate); |
506 | 10.1k | s_begin_inline(s, sptr, endptr); |
507 | 10.1k | if (retcode == scan_Refill) |
508 | 10.0k | goto pause; |
509 | 115 | goto sret; |
510 | 115 | case scanning_comment: |
511 | 0 | s_begin_inline(s, sptr, endptr); |
512 | 0 | goto cont_comment; |
513 | 357k | case scanning_name: |
514 | 357k | goto cont_name; |
515 | 0 | case scanning_string: |
516 | 0 | goto cont_string; |
517 | 0 | default: |
518 | 0 | return_error(gs_error_Fatal); |
519 | 367k | } |
520 | 367k | } |
521 | 3.89G | else { |
522 | | /* We *may* use these in the event of returning to this function after |
523 | | * a interruption, but not every code path below sets them. Set them |
524 | | * to sane values here for safety. We can write the contents of sstate |
525 | | * (back) to pstate before returning. |
526 | | */ |
527 | 3.89G | sstate.s_da.base = sstate.s_da.next = &(sstate.s_da.buf[0]); |
528 | 3.89G | sstate.s_da.limit = sstate.s_da.next; |
529 | 3.89G | sstate.s_da.is_dynamic = false; |
530 | 3.89G | } |
531 | | /* Fetch any state variables that are relevant even if */ |
532 | | /* sstate.s_scan_type == scanning_none. */ |
533 | 3.89G | sstate.s_pstack = pstate->s_pstack; |
534 | 3.89G | sstate.s_pdepth = pstate->s_pdepth; |
535 | 3.89G | ref_assign(&sstate.s_file, &pstate->s_file); |
536 | 3.89G | sstate.s_options = pstate->s_options; |
537 | 3.89G | SCAN_INIT_ERROR(&sstate); |
538 | 3.89G | s_begin_inline(s, sptr, endptr); |
539 | | /* |
540 | | * Loop invariants: |
541 | | * If sstate.s_pstack != 0, myref = osp, and *osp is a valid slot. |
542 | | */ |
543 | 11.0G | top:c = sgetc_inline(s, sptr, endptr); |
544 | 11.0G | if_debug1m('S', imemory, (c >= 32 && c <= 126 ? "`%c'" : c >= 0 ? "`\\%03o'" : "`%d'"), c); |
545 | 11.0G | switch (c) { |
546 | 21.2M | case ' ': |
547 | 21.3M | case '\f': |
548 | 22.6M | case '\t': |
549 | 23.8M | case char_CR: |
550 | 26.4M | case char_EOL: |
551 | 28.8M | case char_NULL: |
552 | 28.8M | goto top; |
553 | 600k | case 0x04: /* see ctrld above */ |
554 | 600k | if (c == ctrld) /* treat as ordinary name char */ |
555 | 4 | goto begin_name; |
556 | | /* fall through */ |
557 | 410M | case '[': |
558 | 781M | case ']': |
559 | 781M | s1[0] = (byte) c; |
560 | 781M | retcode = name_ref(imemory, s1, 1, myref, 1); /* can't fail */ |
561 | 781M | r_set_attrs(myref, a_executable); |
562 | 781M | break; |
563 | 15.3M | case '<': |
564 | 15.3M | if (level2_enabled) { |
565 | 13.6M | ensure2(scanning_none); |
566 | 13.6M | c = sgetc_inline(s, sptr, endptr); |
567 | 13.6M | switch (c) { |
568 | 9.73M | case '<': |
569 | 9.73M | sputback_inline(s, sptr, endptr); |
570 | 9.73M | sstate.s_ss.s_name.s_name_type = 0; |
571 | 9.73M | sstate.s_ss.s_name.s_try_number = false; |
572 | 9.73M | goto try_funny_name; |
573 | 547 | case '~': |
574 | 547 | s_A85D_init_inline(&sstate.s_ss.a85d); |
575 | 547 | sstate.s_ss.st.templat = &s_A85D_template; |
576 | 547 | sstate.s_ss.a85d.require_eod = true; |
577 | | /* If this is an inline ASCII string, interpret it normally, throw an error |
578 | | * if it fails rather than ignoring it as PDF (Acrobat) does. |
579 | | */ |
580 | 547 | sstate.s_ss.a85d.pdf_rules = false; |
581 | 547 | goto str; |
582 | 13.6M | } |
583 | 3.86M | sputback_inline(s, sptr, endptr); |
584 | 3.86M | } |
585 | 5.65M | (void)s_AXD_init_inline(&sstate.s_ss.axd); |
586 | 5.65M | sstate.s_ss.st.templat = &s_AXD_template; |
587 | 171M | str:s_end_inline(s, sptr, endptr); |
588 | 171M | dynamic_init(&sstate.s_da, imemory); |
589 | 171M | cont_string:for (;;) { |
590 | 171M | stream_cursor_write w; |
591 | | |
592 | 171M | w.ptr = sstate.s_da.next - 1; |
593 | 171M | w.limit = sstate.s_da.limit - 1; |
594 | 171M | status = (*sstate.s_ss.st.templat->process) |
595 | 171M | (&sstate.s_ss.st, &s->cursor.r, &w, |
596 | 171M | s->end_status == EOFC); |
597 | 171M | if (!check_only) |
598 | 171M | sstate.s_da.next = w.ptr + 1; |
599 | 171M | switch (status) { |
600 | 569k | case 0: |
601 | 569k | status = s->end_status; |
602 | 569k | if (status < 0) { |
603 | 2.75k | if (status == EOFC) { |
604 | 2.74k | if (check_only) { |
605 | 0 | retcode = scan_Refill; |
606 | 0 | sstate.s_scan_type = scanning_string; |
607 | 0 | goto suspend; |
608 | 0 | } else |
609 | 2.74k | sreturn(gs_error_syntaxerror); |
610 | 0 | } |
611 | 10 | break; |
612 | 2.75k | } |
613 | 566k | s_process_read_buf(s); |
614 | 566k | continue; |
615 | 6.71k | case 1: |
616 | 6.71k | if (!check_only) { |
617 | 6.71k | retcode = dynamic_grow(&sstate.s_da, sstate.s_da.next, max_string_size); |
618 | 6.71k | if (retcode == gs_error_VMerror) { |
619 | 0 | sstate.s_scan_type = scanning_string; |
620 | 0 | goto suspend; |
621 | 6.71k | } else if (retcode < 0) |
622 | 6.71k | sreturn(retcode); |
623 | 6.71k | } |
624 | 6.71k | continue; |
625 | 171M | } |
626 | 171M | break; |
627 | 171M | } |
628 | 171M | s_begin_inline(s, sptr, endptr); |
629 | 171M | switch (status) { |
630 | 1.31k | default: |
631 | | /*case ERRC: */ |
632 | 1.31k | sreturn(gs_error_syntaxerror); |
633 | 0 | case INTC: |
634 | 0 | case CALLC: |
635 | 0 | sstate.s_scan_type = scanning_string; |
636 | 0 | goto pause; |
637 | 171M | case EOFC: |
638 | 171M | ; |
639 | 171M | } |
640 | 171M | retcode = dynamic_make_string(i_ctx_p, myref, &sstate.s_da, sstate.s_da.next); |
641 | 171M | if (retcode < 0) { /* VMerror */ |
642 | 0 | sputback(s); /* rescan ) */ |
643 | 0 | sstate.s_scan_type = scanning_string; |
644 | 0 | goto suspend; |
645 | 0 | } |
646 | 171M | break; |
647 | 171M | case '(': |
648 | 165M | sstate.s_ss.pssd.from_string = |
649 | 165M | ((pstate->s_options & SCAN_FROM_STRING) != 0) && |
650 | 165M | !level2_enabled; |
651 | 165M | s_PSSD_partially_init_inline(&sstate.s_ss.pssd); |
652 | 165M | sstate.s_ss.st.templat = &s_PSSD_template; |
653 | 165M | goto str; |
654 | 862M | case '{': |
655 | 862M | if (sstate.s_pstack == 0) { /* outermost procedure */ |
656 | 191M | if_not_spush1() { |
657 | 0 | sputback_inline(s, sptr, endptr); |
658 | 0 | sstate.s_scan_type = scanning_none; |
659 | 0 | goto pause_ret; |
660 | 0 | } |
661 | 191M | sstate.s_pdepth = ref_stack_count_inline(&o_stack); |
662 | 191M | } |
663 | 862M | make_int(osp, sstate.s_pstack); |
664 | 862M | sstate.s_pstack = ref_stack_count_inline(&o_stack); |
665 | 862M | if_debug3m('S', imemory, "[S{]d=%d, s=%d->%d\n", |
666 | 862M | sstate.s_pdepth, (int)osp->value.intval, sstate.s_pstack); |
667 | 862M | goto snext; |
668 | 9.29M | case '>': |
669 | 9.29M | if (level2_enabled) { |
670 | 9.29M | ensure2(scanning_none); |
671 | 9.29M | sstate.s_ss.s_name.s_name_type = 0; |
672 | 9.29M | sstate.s_ss.s_name.s_try_number = false; |
673 | 9.29M | goto try_funny_name; |
674 | 9.29M | } |
675 | | /* falls through */ |
676 | 290 | case ')': |
677 | 290 | sreturn(gs_error_syntaxerror); |
678 | 860M | case '}': |
679 | 860M | if (sstate.s_pstack == 0) |
680 | 860M | sreturn(gs_error_syntaxerror); |
681 | 860M | osp--; |
682 | 860M | { |
683 | 860M | uint size = ref_stack_count_inline(&o_stack) - sstate.s_pstack; |
684 | 860M | ref arr; |
685 | | |
686 | 860M | if_debug4m('S', imemory, "[S}]d=%"PRIu32", s=%"PRIu32"->%"PRIpsint", c=%"PRIu32"\n", |
687 | 860M | sstate.s_pdepth, sstate.s_pstack, |
688 | 860M | (sstate.s_pstack == sstate.s_pdepth ? 0 : |
689 | 860M | ref_stack_index(&o_stack, size)->value.intval), |
690 | 860M | size + sstate.s_pstack); |
691 | 860M | if (size > max_array_size) |
692 | 860M | sreturn(gs_error_limitcheck); |
693 | 860M | myref = (sstate.s_pstack == sstate.s_pdepth ? pref : &arr); |
694 | 860M | if (check_only) { |
695 | 0 | make_empty_array(myref, 0); |
696 | 0 | ref_stack_pop(&o_stack, size); |
697 | 860M | } else if (ref_array_packing.value.boolval) { |
698 | 847M | retcode = make_packed_array(myref, &o_stack, size, |
699 | 847M | idmemory, "scanner(packed)"); |
700 | 847M | if (retcode < 0) { /* must be VMerror */ |
701 | 0 | osp++; |
702 | 0 | sputback_inline(s, sptr, endptr); |
703 | 0 | sstate.s_scan_type = scanning_none; |
704 | 0 | goto pause_ret; |
705 | 0 | } |
706 | 847M | r_set_attrs(myref, a_executable); |
707 | 847M | } else { |
708 | 12.9M | retcode = ialloc_ref_array(myref, |
709 | 12.9M | a_executable + a_all, size, |
710 | 12.9M | "scanner(proc)"); |
711 | 12.9M | if (retcode < 0) { /* must be VMerror */ |
712 | 0 | osp++; |
713 | 0 | sputback_inline(s, sptr, endptr); |
714 | 0 | sstate.s_scan_type = scanning_none; |
715 | 0 | goto pause_ret; |
716 | 0 | } |
717 | 12.9M | retcode = ref_stack_store(&o_stack, myref, size, 0, 1, |
718 | 12.9M | false, idmemory, "scanner"); |
719 | 12.9M | if (retcode < 0) { |
720 | 0 | ifree_ref_array(myref, "scanner(proc)"); |
721 | 0 | sreturn(retcode); |
722 | 0 | } |
723 | 12.9M | ref_stack_pop(&o_stack, size); |
724 | 12.9M | } |
725 | 860M | if (sstate.s_pstack == sstate.s_pdepth) { /* This was the top-level procedure. */ |
726 | 191M | spop1(); |
727 | 191M | sstate.s_pstack = 0; |
728 | 668M | } else { |
729 | 668M | if (osp < osbot) |
730 | 0 | ref_stack_pop_block(&o_stack); |
731 | 668M | sstate.s_pstack = osp->value.intval; |
732 | 668M | *osp = arr; |
733 | 668M | goto snext; |
734 | 668M | } |
735 | 860M | } |
736 | 191M | break; |
737 | 2.07G | case '/': |
738 | | /* |
739 | | * If the last thing in the input is a '/', don't try to read |
740 | | * any more data. |
741 | | */ |
742 | 2.07G | if (sptr >= endptr && s->end_status != EOFC) { |
743 | 240k | refill2(scanning_none); |
744 | 240k | } |
745 | 2.07G | c = sgetc_inline(s, sptr, endptr); |
746 | 2.07G | if (!PDFScanRules && (c == '/')) { |
747 | 260M | sstate.s_ss.s_name.s_name_type = 2; |
748 | 260M | c = sgetc_inline(s, sptr, endptr); |
749 | 260M | } else |
750 | 1.81G | sstate.s_ss.s_name.s_name_type = 1; |
751 | 2.07G | sstate.s_ss.s_name.s_try_number = false; |
752 | 2.07G | switch (decoder[c]) { |
753 | 202M | case ctype_name: |
754 | 2.07G | default: |
755 | 2.07G | goto do_name; |
756 | 2.07G | case ctype_btoken: |
757 | 2.06k | if (!(ref_binary_object_format.value.intval != 0 && level2_enabled)) |
758 | 0 | goto do_name; |
759 | | /* otherwise, an empty name */ |
760 | 2.33k | case ctype_exception: |
761 | 129k | case ctype_space: |
762 | | /* |
763 | | * Amazingly enough, the Adobe implementations don't accept |
764 | | * / or // followed by [, ], <<, or >>, so we do the same. |
765 | | * (Older versions of our code had a ctype_other case here |
766 | | * that handled these specially.) |
767 | | */ |
768 | 1.37M | case ctype_other: |
769 | 1.37M | if (c == ctrld) /* see above */ |
770 | 0 | goto do_name; |
771 | 1.37M | sstate.s_da.base = sstate.s_da.limit = daptr = 0; |
772 | 1.37M | sstate.s_da.is_dynamic = false; |
773 | 1.37M | goto nx; |
774 | 2.07G | } |
775 | 2.51M | case '%': |
776 | 2.51M | { /* Scan as much as possible within the buffer. */ |
777 | 2.51M | const byte *base = sptr; |
778 | 2.51M | const byte *end; |
779 | | |
780 | 36.8M | while (++sptr < endptr) /* stop 1 char early */ |
781 | 36.8M | switch (*sptr) { |
782 | 30.9k | case char_CR: |
783 | 30.9k | end = sptr; |
784 | 30.9k | if (sptr[1] == char_EOL) |
785 | 2.45k | sptr++; |
786 | 2.49M | cend: /* Check for externally processed comments. */ |
787 | 2.49M | retcode = scan_comment(i_ctx_p, myref, &sstate, |
788 | 2.49M | base, end, false); |
789 | 2.49M | if (retcode != 0) |
790 | 1.09M | goto comment; |
791 | 1.39M | goto top; |
792 | 2.36M | case char_EOL: |
793 | 2.46M | case '\f': |
794 | 2.46M | end = sptr; |
795 | 2.46M | goto cend; |
796 | 36.8M | } |
797 | | /* |
798 | | * We got to the end of the buffer while inside a comment. |
799 | | * If there is a possibility that we must pass the comment |
800 | | * to an external procedure, move what we have collected |
801 | | * so far into a private buffer now. |
802 | | */ |
803 | 25.9k | --sptr; |
804 | 25.9k | sstate.s_da.buf[1] = 0; |
805 | 25.9k | { |
806 | | /* Could be an externally processable comment. */ |
807 | 25.9k | uint len = sptr + 1 - base; |
808 | 25.9k | if (len > sizeof(sstate.s_da.buf)) |
809 | 9 | len = sizeof(sstate.s_da.buf); |
810 | | |
811 | 25.9k | memcpy(sstate.s_da.buf, base, len); |
812 | 25.9k | daptr = sstate.s_da.buf + len; |
813 | 25.9k | } |
814 | 25.9k | sstate.s_da.base = sstate.s_da.buf; |
815 | 25.9k | sstate.s_da.is_dynamic = false; |
816 | 25.9k | } |
817 | | /* Enter here to continue scanning a comment. */ |
818 | | /* daptr must be set. */ |
819 | 7.01M | cont_comment:for (;;) { |
820 | 7.01M | switch ((c = sgetc_inline(s, sptr, endptr))) { |
821 | 6.98M | default: |
822 | 6.98M | if (c < 0) |
823 | 3.97k | switch (c) { |
824 | 0 | case INTC: |
825 | 0 | case CALLC: |
826 | 0 | sstate.s_da.next = daptr; |
827 | 0 | sstate.s_scan_type = scanning_comment; |
828 | 0 | goto pause; |
829 | 3.97k | case EOFC: |
830 | | /* |
831 | | * One would think that an EOF in a comment |
832 | | * should be a syntax error, but there are |
833 | | * quite a number of files that end that way. |
834 | | */ |
835 | 3.97k | goto end_comment; |
836 | 3 | default: |
837 | 3 | sreturn(gs_error_syntaxerror); |
838 | 3.97k | } |
839 | 6.98M | if (daptr < sstate.s_da.buf + max_comment_line) |
840 | 533k | *daptr++ = c; |
841 | 6.98M | continue; |
842 | 715 | case char_CR: |
843 | 20.9k | case char_EOL: |
844 | 21.9k | case '\f': |
845 | 25.9k | end_comment: |
846 | 25.9k | retcode = scan_comment(i_ctx_p, myref, &sstate, |
847 | 25.9k | sstate.s_da.buf, daptr, true); |
848 | 25.9k | if (retcode != 0) |
849 | 12.0k | goto comment; |
850 | 13.8k | goto top; |
851 | 7.01M | } |
852 | 7.01M | } |
853 | | /*NOTREACHED */ |
854 | 923k | case EOFC: |
855 | 923k | if (sstate.s_pstack != 0) { |
856 | 5.90k | if (check_only) |
857 | 0 | goto pause; |
858 | 5.90k | sreturn(gs_error_syntaxerror); |
859 | 0 | } |
860 | 917k | retcode = scan_EOF; |
861 | 917k | break; |
862 | 9 | case ERRC: |
863 | 9 | sreturn(gs_error_ioerror); |
864 | | |
865 | | /* Check for a Level 2 funny name (<< or >>). */ |
866 | | /* c is '<' or '>'. We already did an ensure2. */ |
867 | 19.0M | try_funny_name: |
868 | 19.0M | { |
869 | 19.0M | int c1 = sgetc_inline(s, sptr, endptr); |
870 | | |
871 | 19.0M | if (c1 == c) { |
872 | 19.0M | s1[0] = s1[1] = c; |
873 | 19.0M | name_ref(imemory, s1, 2, myref, 1); /* can't fail */ |
874 | 19.0M | goto have_name; |
875 | 19.0M | } |
876 | 135 | sputback_inline(s, sptr, endptr); |
877 | 135 | } |
878 | 135 | sreturn(gs_error_syntaxerror); |
879 | | |
880 | | /* Handle separately the names that might be a number. */ |
881 | 164M | case '0': |
882 | 1.19G | case '1': |
883 | 1.35G | case '2': |
884 | 1.47G | case '3': |
885 | 1.54G | case '4': |
886 | 1.57G | case '5': |
887 | 1.59G | case '6': |
888 | 1.60G | case '7': |
889 | 1.62G | case '8': |
890 | 1.63G | case '9': |
891 | 1.90G | case '.': |
892 | 1.90G | sign = 0; |
893 | 1.96G | nr: /* |
894 | | * Skip a leading sign, if any, by conditionally passing |
895 | | * sptr + 1 rather than sptr. Also, if the last character |
896 | | * in the buffer is a CR, we must stop the scan 1 character |
897 | | * early, to be sure that we can test for CR+LF within the |
898 | | * buffer, by passing endptr rather than endptr + 1. |
899 | | */ |
900 | 1.96G | retcode = scan_number(sptr + (sign & 1), |
901 | 1.96G | endptr /*(*endptr == char_CR ? endptr : endptr + 1) */ , |
902 | 1.96G | sign, myref, &newptr, i_ctx_p->scanner_options); |
903 | 1.96G | if (retcode == 1 && decoder[newptr[-1]] == ctype_space) { |
904 | 906M | sptr = newptr - 1; |
905 | 906M | if (*sptr == char_CR && sptr[1] == char_EOL) |
906 | 525 | sptr++; |
907 | 906M | retcode = 0; |
908 | 906M | ref_mark_new(myref); |
909 | 906M | break; |
910 | 906M | } |
911 | 1.05G | sstate.s_ss.s_name.s_name_type = 0; |
912 | 1.05G | sstate.s_ss.s_name.s_try_number = true; |
913 | 1.05G | goto do_name; |
914 | 5.32k | case '+': |
915 | 5.32k | sign = 1; |
916 | 5.32k | goto nr; |
917 | 60.5M | case '-': |
918 | 60.5M | sign = -1; |
919 | 60.5M | if(i_ctx_p->scanner_options & SCAN_PDF_INV_NUM) { |
920 | 0 | const byte *osptr = sptr; |
921 | 0 | do { |
922 | | /* This is slightly unpleasant: we have to bounds check the buffer, |
923 | | rather than just incrementing the point until we find a non '-' character. |
924 | | But we cannot differentiate between multiple '-' characters that |
925 | | straddle a buffer boundary, or a token that is only one or more '-' characters. |
926 | | Handling this relies on the fact that the Postscript-based PDF interpreter |
927 | | always uses the "token" operator to tokenize a stream, thus we can assume |
928 | | here that the current buffer contains the entire token. So if we reach |
929 | | the end of the buffer without hitting a character taht is not a '-', we'll reset |
930 | | the buffer pointer, and retry, treating it as a name object. |
931 | | */ |
932 | 0 | if (sptr + 1 > endptr) { |
933 | 0 | sptr = osptr; |
934 | 0 | sstate.s_ss.s_name.s_name_type = 0; |
935 | 0 | sstate.s_ss.s_name.s_try_number = true; |
936 | 0 | goto do_name; |
937 | 0 | } |
938 | 0 | if (*(sptr + 1) == '-') { |
939 | 0 | sptr++; |
940 | 0 | } else |
941 | 0 | break; |
942 | 0 | } while (1); |
943 | 0 | } |
944 | 60.5M | goto nr; |
945 | | |
946 | | /* Check for a binary object */ |
947 | 60.5M | case 128: case 129: case 130: case 131: case 132: case 133: case 134: case 135: |
948 | 266k | case 136: case 137: case 138: case 139: case 140: case 141: case 142: case 143: |
949 | 565k | case 144: case 145: case 146: case 147: case 148: case 149: case 150: case 151: |
950 | 566k | case 152: case 153: case 154: case 155: case 156: case 157: case 158: case 159: |
951 | 566k | if ((ref_binary_object_format.value.intval != 0 && level2_enabled)) { |
952 | 566k | s_end_inline(s, sptr, endptr); |
953 | 566k | retcode = scan_binary_token(i_ctx_p, myref, &sstate); |
954 | 566k | s_begin_inline(s, sptr, endptr); |
955 | 566k | if (retcode == scan_Refill) |
956 | 2.00k | goto pause; |
957 | 564k | break; |
958 | 566k | } |
959 | | /* Not a binary object, fall through. */ |
960 | | |
961 | | /* The default is a name. */ |
962 | 1.14M | default: |
963 | 1.14M | if (c < 0) { |
964 | 446k | dynamic_init(&sstate.s_da, name_memory(imemory)); /* sstate.s_da state must be clean */ |
965 | 446k | sstate.s_scan_type = scanning_none; |
966 | 446k | goto pause; |
967 | 446k | } |
968 | | /* Populate the switch with enough cases to force */ |
969 | | /* simple compilers to use a dispatch rather than tests. */ |
970 | 718k | case '!': |
971 | 1.07M | case '"': |
972 | 3.59M | case '#': |
973 | 14.9M | case '$': |
974 | 14.9M | case '&': |
975 | 15.1M | case '\'': |
976 | 15.2M | case '*': |
977 | 16.4M | case ',': |
978 | 48.0M | case '=': |
979 | 48.0M | case ':': |
980 | 65.7M | case ';': |
981 | 66.2M | case '?': |
982 | 66.2M | case '@': |
983 | 67.7M | case 'A': |
984 | 70.6M | case 'B': |
985 | 79.6M | case 'C': |
986 | 85.6M | case 'D': |
987 | 90.6M | case 'E': |
988 | 96.9M | case 'F': |
989 | 100M | case 'G': |
990 | 103M | case 'H': |
991 | 107M | case 'I': |
992 | 108M | case 'J': |
993 | 108M | case 'K': |
994 | 113M | case 'L': |
995 | 116M | case 'M': |
996 | 125M | case 'N': |
997 | 133M | case 'O': |
998 | 167M | case 'P': |
999 | 172M | case 'Q': |
1000 | 185M | case 'R': |
1001 | 196M | case 'S': |
1002 | 212M | case 'T': |
1003 | 214M | case 'U': |
1004 | 218M | case 'V': |
1005 | 220M | case 'W': |
1006 | 220M | case 'X': |
1007 | 221M | case 'Y': |
1008 | 221M | case 'Z': |
1009 | 221M | case '\\': |
1010 | 221M | case '^': |
1011 | 221M | case '_': |
1012 | 221M | case '`': |
1013 | 353M | case 'a': |
1014 | 519M | case 'b': |
1015 | 746M | case 'c': |
1016 | 1.32G | case 'd': |
1017 | 1.93G | case 'e': |
1018 | 2.04G | case 'f': |
1019 | 2.23G | case 'g': |
1020 | 2.24G | case 'h': |
1021 | 2.83G | case 'i': |
1022 | 2.83G | case 'j': |
1023 | 2.91G | case 'k': |
1024 | 3.02G | case 'l': |
1025 | 3.09G | case 'm': |
1026 | 3.21G | case 'n': |
1027 | 3.27G | case 'o': |
1028 | 3.79G | case 'p': |
1029 | 3.79G | case 'q': |
1030 | 3.97G | case 'r': |
1031 | 4.19G | case 's': |
1032 | 4.25G | case 't': |
1033 | 4.27G | case 'u': |
1034 | 4.27G | case 'v': |
1035 | 4.30G | case 'w': |
1036 | 4.31G | case 'x': |
1037 | 4.31G | case 'y': |
1038 | 4.31G | case 'z': |
1039 | 4.31G | case '|': |
1040 | 4.31G | case '~': |
1041 | 4.31G | begin_name: |
1042 | | /* Common code for scanning a name. */ |
1043 | | /* sstate.s_ss.s_name.s_try_number and sstate.s_ss.s_name.s_name_type are already set. */ |
1044 | | /* We know c has ctype_name (or maybe ctype_btoken, */ |
1045 | | /* or is ^D) or is a digit. */ |
1046 | 4.31G | sstate.s_ss.s_name.s_name_type = 0; |
1047 | 4.31G | sstate.s_ss.s_name.s_try_number = false; |
1048 | 7.44G | do_name: |
1049 | | /* Try to scan entirely within the stream buffer. */ |
1050 | | /* We stop 1 character early, so we don't switch buffers */ |
1051 | | /* looking ahead if the name is terminated by \r\n. */ |
1052 | 7.44G | sstate.s_da.base = (byte *) sptr; |
1053 | 7.44G | sstate.s_da.is_dynamic = false; |
1054 | 7.44G | { |
1055 | 7.44G | const byte *endp1 = endptr - 1; |
1056 | | |
1057 | 51.5G | do { |
1058 | 51.5G | if (sptr >= endp1) /* stop 1 early! */ |
1059 | 6.88M | goto dyn_name; |
1060 | 51.5G | } |
1061 | 51.5G | while (decoder[*++sptr] <= max_name_ctype || *sptr == ctrld); /* digit or name */ |
1062 | 7.44G | } |
1063 | | /* Name ended within the buffer. */ |
1064 | 7.44G | daptr = (byte *) sptr; |
1065 | 7.44G | c = *sptr; |
1066 | 7.44G | goto nx; |
1067 | 6.88M | dyn_name: /* Name extended past end of buffer. */ |
1068 | 6.88M | s_end_inline(s, sptr, endptr); |
1069 | | /* Initialize the dynamic area. */ |
1070 | | /* We have to do this before the next */ |
1071 | | /* sgetc, which will overwrite the buffer. */ |
1072 | 6.88M | sstate.s_da.limit = (byte *)++ sptr; |
1073 | 6.88M | sstate.s_da.memory = name_memory(imemory); |
1074 | 6.88M | retcode = dynamic_grow(&sstate.s_da, sstate.s_da.limit, name_max_string); |
1075 | 6.88M | if (retcode < 0) { |
1076 | 32 | dynamic_save(&sstate.s_da); |
1077 | 32 | if (retcode != gs_error_VMerror) |
1078 | 32 | sreturn(retcode); |
1079 | 0 | sstate.s_scan_type = scanning_name; |
1080 | 0 | goto pause_ret; |
1081 | 32 | } |
1082 | 6.88M | daptr = sstate.s_da.next; |
1083 | | /* Enter here to continue scanning a name. */ |
1084 | | /* daptr must be set. */ |
1085 | 7.24M | cont_name:s_begin_inline(s, sptr, endptr); |
1086 | 24.3M | while (decoder[c = sgetc_inline(s, sptr, endptr)] <= max_name_ctype || c == ctrld) { |
1087 | 17.0M | if (daptr == sstate.s_da.limit) { |
1088 | 10.6k | retcode = dynamic_grow(&sstate.s_da, daptr, |
1089 | 10.6k | name_max_string); |
1090 | 10.6k | if (retcode < 0) { |
1091 | 69 | dynamic_save(&sstate.s_da); |
1092 | 69 | if (retcode != gs_error_VMerror) |
1093 | 69 | sreturn(retcode); |
1094 | 0 | sputback_inline(s, sptr, endptr); |
1095 | 0 | sstate.s_scan_type = scanning_name; |
1096 | 0 | goto pause_ret; |
1097 | 69 | } |
1098 | 10.6k | daptr = sstate.s_da.next; |
1099 | 10.6k | } |
1100 | 17.0M | *daptr++ = c; |
1101 | 17.0M | } |
1102 | 7.45G | nx:switch (decoder[c]) { |
1103 | 3.83G | case ctype_other: |
1104 | 3.83G | if (c == ctrld) /* see above */ |
1105 | 0 | break; |
1106 | 3.83G | case ctype_btoken: |
1107 | 3.83G | sputback_inline(s, sptr, endptr); |
1108 | 3.83G | break; |
1109 | 3.60G | case ctype_space: |
1110 | | /* Check for \r\n */ |
1111 | 3.60G | if (c == char_CR) { |
1112 | 583k | if (sptr >= endptr) { /* ensure2 *//* We have to check specially for */ |
1113 | | /* the case where the very last */ |
1114 | | /* character of a file is a CR. */ |
1115 | 721 | if (s->end_status != EOFC) { |
1116 | 609 | sptr--; |
1117 | 609 | goto pause_name; |
1118 | 609 | } |
1119 | 582k | } else if (sptr[1] == char_EOL) |
1120 | 12.9k | sptr++; |
1121 | 583k | } |
1122 | 3.60G | break; |
1123 | 3.60G | case ctype_exception: |
1124 | 2.89M | switch (c) { |
1125 | 0 | case INTC: |
1126 | 356k | case CALLC: |
1127 | 356k | goto pause_name; |
1128 | 6 | case ERRC: |
1129 | 6 | sreturn(gs_error_ioerror); |
1130 | 2.53M | case EOFC: |
1131 | 2.53M | break; |
1132 | 2.89M | } |
1133 | 7.45G | } |
1134 | | /* Check for a number */ |
1135 | 7.45G | if (sstate.s_ss.s_name.s_try_number) { |
1136 | 1.05G | const byte *base = sstate.s_da.base; |
1137 | | |
1138 | 1.05G | scan_sign(sign, base); |
1139 | 1.05G | retcode = scan_number(base, daptr, sign, myref, &newptr, i_ctx_p->scanner_options); |
1140 | 1.05G | if (retcode == 1) { |
1141 | 1.21M | ref_mark_new(myref); |
1142 | 1.21M | retcode = 0; |
1143 | 1.05G | } else if (retcode != gs_error_syntaxerror) { |
1144 | 783M | dynamic_free(&sstate.s_da); |
1145 | 783M | if (sstate.s_ss.s_name.s_name_type == 2) |
1146 | 783M | sreturn(gs_error_syntaxerror); |
1147 | 783M | break; /* might be gs_error_limitcheck */ |
1148 | 783M | } |
1149 | 1.05G | } |
1150 | 6.66G | if (sstate.s_da.is_dynamic) { /* We've already allocated the string on the heap. */ |
1151 | 4.87M | uint size = daptr - sstate.s_da.base; |
1152 | | |
1153 | 4.87M | retcode = name_ref(imemory, sstate.s_da.base, size, myref, -1); |
1154 | 4.87M | if (retcode >= 0) { |
1155 | 4.44M | dynamic_free(&sstate.s_da); |
1156 | 4.44M | } else { |
1157 | 438k | retcode = dynamic_resize(&sstate.s_da, size); |
1158 | 438k | if (retcode < 0) { /* VMerror */ |
1159 | 0 | if (c != EOFC) |
1160 | 0 | sputback_inline(s, sptr, endptr); |
1161 | 0 | sstate.s_scan_type = scanning_name; |
1162 | 0 | goto pause_ret; |
1163 | 0 | } |
1164 | 438k | retcode = name_ref(imemory, sstate.s_da.base, size, myref, 2); |
1165 | 438k | } |
1166 | 6.66G | } else { |
1167 | 6.66G | retcode = name_ref(imemory, sstate.s_da.base, (uint) (daptr - sstate.s_da.base), |
1168 | 6.66G | myref, !s->foreign); |
1169 | 6.66G | } |
1170 | | /* Done scanning. Check for preceding /'s. */ |
1171 | 6.66G | if (retcode < 0) { |
1172 | 0 | if (retcode != gs_error_VMerror) |
1173 | 0 | sreturn(retcode); |
1174 | 0 | if (!sstate.s_da.is_dynamic) { |
1175 | 0 | sstate.s_da.next = daptr; |
1176 | 0 | dynamic_save(&sstate.s_da); |
1177 | 0 | } |
1178 | 0 | if (c != EOFC) |
1179 | 0 | sputback_inline(s, sptr, endptr); |
1180 | 0 | sstate.s_scan_type = scanning_name; |
1181 | 0 | goto pause_ret; |
1182 | 0 | } |
1183 | 6.68G | have_name:switch (sstate.s_ss.s_name.s_name_type) { |
1184 | 4.61G | case 0: /* ordinary executable name */ |
1185 | 4.61G | if (r_has_type(myref, t_name)) /* i.e., not a number */ |
1186 | 4.61G | r_set_attrs(myref, a_executable); |
1187 | 6.42G | case 1: /* quoted name */ |
1188 | 6.42G | break; |
1189 | 260M | case 2: /* immediate lookup */ |
1190 | 260M | { |
1191 | 260M | ref *pvalue; |
1192 | | |
1193 | 260M | if (!r_has_type(myref, t_name) || |
1194 | 260M | (pvalue = dict_find_name(myref)) == 0) { |
1195 | 132 | ref_assign(&sstate.s_error.object, myref); |
1196 | 132 | r_set_attrs(&sstate.s_error.object, |
1197 | 132 | a_executable); /* Adobe compatibility */ |
1198 | 132 | sreturn(gs_error_undefined); |
1199 | 0 | } |
1200 | 260M | if (sstate.s_pstack != 0 && |
1201 | 260M | r_space(pvalue) > ialloc_space(idmemory) |
1202 | 260M | ) |
1203 | 260M | sreturn(gs_error_invalidaccess); |
1204 | 260M | ref_assign_new(myref, pvalue); |
1205 | 260M | } |
1206 | 6.68G | } |
1207 | 11.0G | } |
1208 | 9.52G | sret:if (retcode < 0) { |
1209 | 16.5k | s_end_inline(s, sptr, endptr); |
1210 | 16.5k | pstate->s_error = sstate.s_error; |
1211 | 16.5k | if (sstate.s_pstack != 0) { |
1212 | 7.54k | if (retcode == gs_error_undefined) |
1213 | 91 | *pref = *osp; /* return undefined name as error token */ |
1214 | 7.54k | ref_stack_pop(&o_stack, |
1215 | 7.54k | ref_stack_count(&o_stack) - (sstate.s_pdepth - 1)); |
1216 | 7.54k | } |
1217 | 16.5k | return retcode; |
1218 | 16.5k | } |
1219 | | /* If we are at the top level, return the object, */ |
1220 | | /* otherwise keep going. */ |
1221 | 9.52G | if (sstate.s_pstack == 0) { |
1222 | 3.89G | s_end_inline(s, sptr, endptr); |
1223 | 3.89G | return retcode; |
1224 | 3.89G | } |
1225 | 7.15G | snext:if_not_spush1() { |
1226 | 7 | s_end_inline(s, sptr, endptr); |
1227 | 7 | sstate.s_scan_type = scanning_none; |
1228 | 7 | goto save; |
1229 | 7 | } |
1230 | 7.15G | myref = osp; |
1231 | 7.15G | goto top; |
1232 | | |
1233 | | /* Pause for an interrupt or callout. */ |
1234 | 357k | pause_name: |
1235 | | /* If we're still scanning within the stream buffer, */ |
1236 | | /* move the characters to the private buffer (sstate.s_da.buf) now. */ |
1237 | 357k | sstate.s_da.next = daptr; |
1238 | 357k | dynamic_save(&sstate.s_da); |
1239 | 357k | sstate.s_scan_type = scanning_name; |
1240 | 1.05M | pause: |
1241 | 1.05M | retcode = scan_Refill; |
1242 | 1.05M | pause_ret: |
1243 | 1.05M | s_end_inline(s, sptr, endptr); |
1244 | 1.05M | suspend: |
1245 | 1.05M | if (sstate.s_pstack != 0) |
1246 | 9.18k | osp--; /* myref */ |
1247 | 2.16M | save: |
1248 | 2.16M | *pstate = sstate; |
1249 | 2.16M | return retcode; |
1250 | | |
1251 | | /* Handle a scanned comment. */ |
1252 | 1.10M | comment: |
1253 | 1.10M | if (retcode < 0) |
1254 | 0 | goto sret; |
1255 | 1.10M | s_end_inline(s, sptr, endptr); |
1256 | 1.10M | sstate.s_scan_type = scanning_none; |
1257 | 1.10M | goto save; |
1258 | 1.10M | } |