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