/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 | 10.6M | { |
62 | 10.6M | pda->is_dynamic = false; |
63 | 10.6M | pda->limit = pda->buf + sizeof(pda->buf); |
64 | 10.6M | pda->next = pda->base = pda->buf; |
65 | 10.6M | pda->memory = mem; |
66 | 10.6M | } |
67 | | |
68 | | /* Free a dynamic string. */ |
69 | | static void |
70 | | dynamic_free(da_ptr pda) |
71 | 82.1M | { |
72 | 82.1M | if (pda->is_dynamic) |
73 | 605k | gs_free_string(pda->memory, pda->base, da_size(pda), "scanner"); |
74 | 82.1M | } |
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 | 11.3M | { |
81 | 11.3M | uint old_size = da_size(pda); |
82 | 11.3M | uint pos = pda->next - pda->base; |
83 | 11.3M | gs_memory_t *mem = pda->memory; |
84 | 11.3M | byte *base; |
85 | | |
86 | 11.3M | if (pda->is_dynamic) { |
87 | 67.8k | base = gs_resize_string(mem, pda->base, old_size, |
88 | 67.8k | new_size, "scanner"); |
89 | 67.8k | if (base == 0) |
90 | 0 | return_error(gs_error_VMerror); |
91 | 11.2M | } else { /* switching from static to dynamic */ |
92 | 11.2M | base = gs_alloc_string(mem, new_size, "scanner"); |
93 | 11.2M | if (base == 0) |
94 | 0 | return_error(gs_error_VMerror); |
95 | 11.2M | memcpy(base, pda->base, min(old_size, new_size)); |
96 | 11.2M | pda->is_dynamic = true; |
97 | 11.2M | } |
98 | 11.3M | pda->base = base; |
99 | 11.3M | pda->next = base + pos; |
100 | 11.3M | pda->limit = base + new_size; |
101 | 11.3M | return 0; |
102 | 11.3M | } |
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 | 673k | { |
111 | 673k | uint old_size = da_size(pda); |
112 | 673k | uint new_size = (old_size < 10 ? 20 : |
113 | 673k | old_size >= (max_size >> 1) ? max_size : |
114 | 144k | old_size << 1); |
115 | 673k | int code; |
116 | | |
117 | 673k | pda->next = next; |
118 | 673k | if (old_size >= max_size) |
119 | 6 | return_error(gs_error_limitcheck); |
120 | 673k | 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 | 673k | return code; |
127 | 673k | } |
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 | 48.4k | { |
134 | 48.4k | if (!pda->is_dynamic && pda->base != pda->buf) { |
135 | 3 | int len = da_size(pda); |
136 | | |
137 | 3 | 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 | 3 | if (pda->base != NULL) |
145 | 2 | memcpy(pda->buf, pda->base, len); |
146 | 3 | pda->next = pda->buf + len; |
147 | 3 | pda->base = pda->buf; |
148 | 3 | } |
149 | 48.4k | } |
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 | 10.5M | { |
155 | 10.5M | uint size = (pda->next = next) - pda->base; |
156 | 10.5M | int code = dynamic_resize(pda, size); |
157 | | |
158 | 10.5M | if (code < 0) |
159 | 0 | return code; |
160 | 10.5M | make_tasv_new(pref, t_string, |
161 | 10.5M | a_all | imemory_space((gs_ref_memory_t *) pda->memory), |
162 | 10.5M | size, bytes, pda->base); |
163 | 10.5M | return 0; |
164 | 10.5M | } |
165 | | |
166 | | /* ------ Main scanner ------ */ |
167 | | |
168 | | /* GC procedures */ |
169 | | static |
170 | | CLEAR_MARKS_PROC(scanner_clear_marks) |
171 | 18 | { |
172 | 18 | scanner_state *const ssptr = vptr; |
173 | | |
174 | 18 | r_clear_attrs(&ssptr->s_file, l_mark); |
175 | 18 | r_clear_attrs(&ssptr->s_ss.binary.bin_array, l_mark); |
176 | 18 | r_clear_attrs(&ssptr->s_error.object, l_mark); |
177 | 18 | } |
178 | | static |
179 | 56 | ENUM_PTRS_WITH(scanner_enum_ptrs, scanner_state *ssptr) return 0; |
180 | 14 | case 0: |
181 | 14 | ENUM_RETURN_REF(&ssptr->s_file); |
182 | 14 | case 1: |
183 | 14 | ENUM_RETURN_REF(&ssptr->s_error.object); |
184 | 14 | case 2: |
185 | 14 | if (ssptr->s_scan_type == scanning_none || |
186 | 14 | !ssptr->s_da.is_dynamic |
187 | 14 | ) |
188 | 13 | ENUM_RETURN(0); |
189 | 1 | return ENUM_STRING2(ssptr->s_da.base, da_size(&ssptr->s_da)); |
190 | 14 | case 3: |
191 | 14 | if (ssptr->s_scan_type != scanning_binary) |
192 | 14 | return 0; |
193 | 56 | ENUM_RETURN_REF(&ssptr->s_ss.binary.bin_array); |
194 | 56 | ENUM_PTRS_END |
195 | 14 | static RELOC_PTRS_WITH(scanner_reloc_ptrs, scanner_state *ssptr) |
196 | 14 | { |
197 | 14 | RELOC_REF_VAR(ssptr->s_file); |
198 | 14 | r_clear_attrs(&ssptr->s_file, l_mark); |
199 | 14 | if (ssptr->s_scan_type != scanning_none && ssptr->s_da.is_dynamic) { |
200 | 1 | gs_string sda; |
201 | | |
202 | 1 | sda.data = ssptr->s_da.base; |
203 | 1 | sda.size = da_size(&ssptr->s_da); |
204 | 1 | RELOC_STRING_VAR(sda); |
205 | 1 | ssptr->s_da.limit = sda.data + sda.size; |
206 | 1 | ssptr->s_da.next = sda.data + (ssptr->s_da.next - ssptr->s_da.base); |
207 | 1 | ssptr->s_da.base = sda.data; |
208 | 1 | } |
209 | 14 | 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 | 14 | RELOC_REF_VAR(ssptr->s_error.object); |
214 | 14 | r_clear_attrs(&ssptr->s_error.object, l_mark); |
215 | 14 | } |
216 | 14 | 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 | 356M | { |
224 | 356M | ref_assign(&sstate->s_file, fop); |
225 | 356M | sstate->s_scan_type = scanning_none; |
226 | 356M | sstate->s_pstack = 0; |
227 | 356M | sstate->s_options = options; |
228 | 356M | SCAN_INIT_ERROR(sstate); |
229 | 356M | } |
230 | | void gs_scanner_init_stream_options(scanner_state *sstate, stream *s, |
231 | | int options) |
232 | 204k | { |
233 | | /* |
234 | | * The file 'object' will never be accessed, but it must be in correct |
235 | | * form for the GC. |
236 | | */ |
237 | 204k | ref fobj; |
238 | | |
239 | 204k | make_file(&fobj, a_read, 0, s); |
240 | 204k | gs_scanner_init_options(sstate, &fobj, options); |
241 | 204k | } |
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 | 1.50k | { |
251 | 1.50k | if (!r_has_type(&pstate->s_error.object, t__invalid)) { |
252 | 6 | ref_assign(pseo, &pstate->s_error.object); |
253 | 6 | return 0; |
254 | 6 | } |
255 | 1.49k | if (pstate->s_error.string[0]) { |
256 | 561 | int len = strlen(pstate->s_error.string); |
257 | | |
258 | 561 | if (pstate->s_error.is_name) { |
259 | 14 | int code = name_ref(imemory, (const byte *)pstate->s_error.string, len, pseo, 1); |
260 | | |
261 | 14 | if (code < 0) |
262 | 0 | return code; |
263 | 14 | r_set_attrs(pseo, a_executable); /* Adobe compatibility */ |
264 | 14 | return 0; |
265 | 547 | } else { |
266 | 547 | byte *estr = ialloc_string(len, "gs_scanner_error_object"); |
267 | | |
268 | 547 | if (estr == 0) |
269 | 0 | return -1; /* VMerror */ |
270 | 547 | memcpy(estr, (const byte *)pstate->s_error.string, len); |
271 | 547 | make_string(pseo, a_all | icurrent_space, len, estr); |
272 | 547 | return 0; |
273 | 547 | } |
274 | 561 | } |
275 | 933 | return -1; /* no error object */ |
276 | 1.49k | } |
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 | 143k | { |
285 | 143k | const ref *const fop = &sstate->s_file; |
286 | 143k | stream *s = fptr(fop); |
287 | 143k | uint avail = sbufavailable(s); |
288 | 143k | int status; |
289 | | |
290 | 143k | if (s->end_status == EOFC) { |
291 | | /* More data needed, but none available, so this is a syntax error. */ |
292 | 42 | return_error(gs_error_syntaxerror); |
293 | 42 | } |
294 | 143k | status = s_process_read_buf(s); |
295 | 143k | if (sbufavailable(s) > avail) |
296 | 37.4k | return 0; |
297 | 106k | if (status == 0) |
298 | 106k | status = s->end_status; |
299 | 106k | switch (status) { |
300 | 58 | case EOFC: |
301 | | /* We just discovered that we're at EOF. */ |
302 | | /* Let the caller find this out. */ |
303 | 58 | return 0; |
304 | 0 | case ERRC: |
305 | 0 | return_error(gs_error_ioerror); |
306 | 0 | case INTC: |
307 | 106k | case CALLC: |
308 | 106k | { |
309 | 106k | ref rstate[1]; |
310 | 106k | scanner_state *pstate; |
311 | | |
312 | 106k | if (save) { |
313 | 96.6k | pstate = (scanner_state *) |
314 | 96.6k | ialloc_struct(scanner_state_dynamic, &st_scanner_state_dynamic, |
315 | 96.6k | "gs_scan_handle_refill"); |
316 | 96.6k | if (pstate == 0) |
317 | 0 | return_error(gs_error_VMerror); |
318 | 96.6k | ((scanner_state_dynamic *)pstate)->mem = imemory; |
319 | 96.6k | *pstate = *sstate; |
320 | 96.6k | } else |
321 | 9.66k | pstate = sstate; |
322 | 106k | make_istruct(&rstate[0], 0, pstate); |
323 | 106k | return s_handle_read_exception(i_ctx_p, status, fop, |
324 | 106k | rstate, 1, cont); |
325 | 106k | } |
326 | 106k | } |
327 | | /* No more data available, but no exception. */ |
328 | | /* A filter is consuming headers but returns nothing. */ |
329 | 0 | return 0; |
330 | 106k | } |
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 | 252k | { |
340 | 252k | uint len = (uint) (end - base); |
341 | 252k | int code; |
342 | | #ifdef DEBUG |
343 | | const char *sstr = (saved ? ">" : ""); |
344 | | #endif |
345 | | |
346 | 252k | 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 | 128k | if (pstate->s_options & SCAN_PROCESS_DSC_COMMENTS) { |
356 | 126k | code = scan_DSC_Comment; |
357 | 126k | goto comment; |
358 | 126k | } |
359 | | /* Treat as an ordinary comment. */ |
360 | 128k | } |
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 | 125k | if (pstate->s_options & SCAN_PROCESS_COMMENTS) { |
371 | 0 | code = scan_Comment; |
372 | 0 | goto comment; |
373 | 0 | } |
374 | 125k | return 0; |
375 | 126k | comment: |
376 | 126k | { |
377 | 126k | byte *cstr = ialloc_string(len, "scan_comment"); |
378 | | |
379 | 126k | if (cstr == 0) |
380 | 0 | return_error(gs_error_VMerror); |
381 | 126k | memcpy(cstr, base, len); |
382 | 126k | make_string(pref, a_all | icurrent_space, len, cstr); |
383 | 126k | } |
384 | 0 | return code; |
385 | 126k | } |
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 | 146k | { |
394 | 146k | stream st; |
395 | 146k | stream *s = &st; |
396 | 146k | scanner_state state; |
397 | 146k | int code; |
398 | | |
399 | 146k | if (!r_has_attr(pstr, a_read)) |
400 | 0 | return_error(gs_error_invalidaccess); |
401 | 146k | s_init(s, NULL); |
402 | 146k | sread_string(s, pstr->value.bytes, r_size(pstr)); |
403 | 146k | gs_scanner_init_stream_options(&state, s, options | SCAN_FROM_STRING); |
404 | 146k | switch (code = gs_scan_token(i_ctx_p, pref, &state)) { |
405 | 1 | default: /* error or comment */ |
406 | 1 | if (code < 0) |
407 | 1 | break; |
408 | | /* falls through */ |
409 | 146k | case 0: /* read a token */ |
410 | 146k | case scan_BOS: |
411 | 146k | { |
412 | 146k | uint pos = stell(s); |
413 | | |
414 | 146k | pstr->value.bytes += pos; |
415 | 146k | r_dec_size(pstr, pos); |
416 | 146k | } |
417 | 146k | break; |
418 | 0 | case scan_Refill: /* error */ |
419 | 0 | code = gs_note_error(gs_error_syntaxerror); |
420 | 2 | case scan_EOF: |
421 | 2 | break; |
422 | 146k | } |
423 | 146k | if (code < 0) |
424 | 1 | gs_scanner_error_object(i_ctx_p, &state, &i_ctx_p->error_object); |
425 | 146k | return code; |
426 | 146k | } |
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 | 356M | { |
439 | 356M | stream *const s = pstate->s_file.value.pfile; |
440 | 356M | ref *myref = pref; |
441 | 356M | int retcode = 0; |
442 | 356M | int c; |
443 | | |
444 | 356M | s_declare_inline(s, sptr, endptr); |
445 | 356M | const byte *newptr; |
446 | 356M | byte *daptr; |
447 | | |
448 | 356M | #define sreturn(code)\ |
449 | 356M | { retcode = gs_note_error(code); goto sret; } |
450 | 356M | #define if_not_spush1()\ |
451 | 393M | if ( osp < ostop ) osp++;\ |
452 | 393M | else if ( (retcode = ref_stack_push(&o_stack, 1)) >= 0 )\ |
453 | 3.30k | ;\ |
454 | 3.30k | else |
455 | 356M | #define spop1()\ |
456 | 356M | if ( osp >= osbot ) osp--;\ |
457 | 12.8M | else ref_stack_pop(&o_stack, 1) |
458 | 356M | int max_name_ctype = |
459 | 356M | ((ref_binary_object_format.value.intval != 0 && level2_enabled)? ctype_name : ctype_btoken); |
460 | | |
461 | 356M | #define scan_sign(sign, ptr)\ |
462 | 356M | switch ( *ptr ) {\ |
463 | 258k | case '-': sign = -1; ptr++; break;\ |
464 | 195 | case '+': sign = 1; ptr++; break;\ |
465 | 107M | default: sign = 0;\ |
466 | 108M | } |
467 | 356M | #define refill2_back(styp,nback)\ |
468 | 356M | BEGIN sptr -= nback; sstate.s_scan_type = styp; goto pause; END |
469 | 356M | #define ensure2_back(styp,nback)\ |
470 | 356M | if ( sptr >= endptr ) refill2_back(styp,nback) |
471 | 356M | #define ensure2(styp) ensure2_back(styp, 1) |
472 | 356M | #define refill2(styp) refill2_back(styp, 1) |
473 | 356M | byte s1[2]; |
474 | 356M | const byte *const decoder = scan_char_decoder; |
475 | 356M | int status; |
476 | 356M | int sign; |
477 | 356M | const bool check_only = (pstate->s_options & SCAN_CHECK_ONLY) != 0; |
478 | 356M | 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 | 356M | const int ctrld = (pstate->s_options & SCAN_FROM_STRING || |
485 | 356M | PDFScanRules ? 0x04 : 0xffff); |
486 | 356M | scanner_state sstate; |
487 | | |
488 | 356M | sptr = endptr = NULL; /* Quiet compiler */ |
489 | 356M | if (pstate->s_pstack != 0) { |
490 | 27.1k | if_not_spush1() |
491 | 0 | return retcode; |
492 | 27.1k | myref = osp; |
493 | 27.1k | } |
494 | | /* Check whether we are resuming after an interruption. */ |
495 | 356M | if (pstate->s_scan_type != scanning_none) { |
496 | 48.8k | sstate = *pstate; |
497 | 48.8k | 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 | 12 | uint next = sstate.s_da.next - sstate.s_da.base; |
501 | 12 | uint limit = sstate.s_da.limit - sstate.s_da.base; |
502 | | |
503 | 12 | sstate.s_da.base = sstate.s_da.buf; |
504 | 12 | sstate.s_da.next = sstate.s_da.buf + next; |
505 | 12 | sstate.s_da.limit = sstate.s_da.buf + limit; |
506 | 12 | } |
507 | 48.8k | daptr = sstate.s_da.next; |
508 | 48.8k | switch (sstate.s_scan_type) { |
509 | 420 | case scanning_binary: |
510 | 420 | retcode = (*sstate.s_ss.binary.cont) |
511 | 420 | (i_ctx_p, myref, &sstate); |
512 | 420 | s_begin_inline(s, sptr, endptr); |
513 | 420 | if (retcode == scan_Refill) |
514 | 413 | goto pause; |
515 | 7 | goto sret; |
516 | 7 | case scanning_comment: |
517 | 0 | s_begin_inline(s, sptr, endptr); |
518 | 0 | goto cont_comment; |
519 | 48.4k | case scanning_name: |
520 | 48.4k | goto cont_name; |
521 | 0 | case scanning_string: |
522 | 0 | goto cont_string; |
523 | 0 | default: |
524 | 0 | return_error(gs_error_Fatal); |
525 | 48.8k | } |
526 | 48.8k | } |
527 | 356M | 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 | 356M | sstate.s_da.base = sstate.s_da.next = &(sstate.s_da.buf[0]); |
534 | 356M | sstate.s_da.limit = sstate.s_da.next; |
535 | 356M | sstate.s_da.is_dynamic = false; |
536 | 356M | } |
537 | | /* Fetch any state variables that are relevant even if */ |
538 | | /* sstate.s_scan_type == scanning_none. */ |
539 | 356M | sstate.s_pstack = pstate->s_pstack; |
540 | 356M | sstate.s_pdepth = pstate->s_pdepth; |
541 | 356M | ref_assign(&sstate.s_file, &pstate->s_file); |
542 | 356M | sstate.s_options = pstate->s_options; |
543 | 356M | SCAN_INIT_ERROR(&sstate); |
544 | 356M | 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 | 741M | top:c = sgetc_inline(s, sptr, endptr); |
550 | 741M | if_debug1m('S', imemory, (c >= 32 && c <= 126 ? "`%c'" : c >= 0 ? "`\\%03o'" : "`%d'"), c); |
551 | 741M | switch (c) { |
552 | 2.07M | case ' ': |
553 | 2.07M | case '\f': |
554 | 2.08M | case '\t': |
555 | 2.10M | case char_CR: |
556 | 2.32M | case char_EOL: |
557 | 3.52M | case char_NULL: |
558 | 3.52M | goto top; |
559 | 105k | case 0x04: /* see ctrld above */ |
560 | 105k | if (c == ctrld) /* treat as ordinary name char */ |
561 | 0 | goto begin_name; |
562 | | /* fall through */ |
563 | 41.1M | case '[': |
564 | 80.2M | case ']': |
565 | 80.2M | s1[0] = (byte) c; |
566 | 80.2M | retcode = name_ref(imemory, s1, 1, myref, 1); /* can't fail */ |
567 | 80.2M | r_set_attrs(myref, a_executable); |
568 | 80.2M | break; |
569 | 811k | case '<': |
570 | 811k | if (level2_enabled) { |
571 | 744k | ensure2(scanning_none); |
572 | 744k | c = sgetc_inline(s, sptr, endptr); |
573 | 744k | switch (c) { |
574 | 494k | case '<': |
575 | 494k | sputback_inline(s, sptr, endptr); |
576 | 494k | sstate.s_ss.s_name.s_name_type = 0; |
577 | 494k | sstate.s_ss.s_name.s_try_number = false; |
578 | 494k | goto try_funny_name; |
579 | 59 | case '~': |
580 | 59 | s_A85D_init_inline(&sstate.s_ss.a85d); |
581 | 59 | sstate.s_ss.st.templat = &s_A85D_template; |
582 | 59 | 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 | 59 | sstate.s_ss.a85d.pdf_rules = false; |
587 | 59 | goto str; |
588 | 744k | } |
589 | 249k | sputback_inline(s, sptr, endptr); |
590 | 249k | } |
591 | 316k | (void)s_AXD_init_inline(&sstate.s_ss.axd); |
592 | 316k | sstate.s_ss.st.templat = &s_AXD_template; |
593 | 10.5M | str:s_end_inline(s, sptr, endptr); |
594 | 10.5M | dynamic_init(&sstate.s_da, imemory); |
595 | 10.6M | cont_string:for (;;) { |
596 | 10.6M | stream_cursor_write w; |
597 | | |
598 | 10.6M | w.ptr = sstate.s_da.next - 1; |
599 | 10.6M | w.limit = sstate.s_da.limit - 1; |
600 | 10.6M | status = (*sstate.s_ss.st.templat->process) |
601 | 10.6M | (&sstate.s_ss.st, &s->cursor.r, &w, |
602 | 10.6M | s->end_status == EOFC); |
603 | 10.6M | if (!check_only) |
604 | 10.6M | sstate.s_da.next = w.ptr + 1; |
605 | 10.6M | switch (status) { |
606 | 101k | case 0: |
607 | 101k | status = s->end_status; |
608 | 101k | if (status < 0) { |
609 | 210 | if (status == EOFC) { |
610 | 210 | if (check_only) { |
611 | 0 | retcode = scan_Refill; |
612 | 0 | sstate.s_scan_type = scanning_string; |
613 | 0 | goto suspend; |
614 | 0 | } else |
615 | 210 | sreturn(gs_error_syntaxerror); |
616 | 0 | } |
617 | 0 | break; |
618 | 210 | } |
619 | 100k | s_process_read_buf(s); |
620 | 100k | continue; |
621 | 504 | case 1: |
622 | 504 | if (!check_only) { |
623 | 504 | retcode = dynamic_grow(&sstate.s_da, sstate.s_da.next, max_string_size); |
624 | 504 | if (retcode == gs_error_VMerror) { |
625 | 0 | sstate.s_scan_type = scanning_string; |
626 | 0 | goto suspend; |
627 | 504 | } else if (retcode < 0) |
628 | 504 | sreturn(retcode); |
629 | 504 | } |
630 | 504 | continue; |
631 | 10.6M | } |
632 | 10.5M | break; |
633 | 10.6M | } |
634 | 10.5M | s_begin_inline(s, sptr, endptr); |
635 | 10.5M | switch (status) { |
636 | 143 | default: |
637 | | /*case ERRC: */ |
638 | 143 | 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 | 10.5M | case EOFC: |
644 | 10.5M | ; |
645 | 10.5M | } |
646 | 10.5M | retcode = dynamic_make_string(i_ctx_p, myref, &sstate.s_da, sstate.s_da.next); |
647 | 10.5M | if (retcode < 0) { /* VMerror */ |
648 | 0 | sputback(s); /* rescan ) */ |
649 | 0 | sstate.s_scan_type = scanning_string; |
650 | 0 | goto suspend; |
651 | 0 | } |
652 | 10.5M | break; |
653 | 10.5M | case '(': |
654 | 10.2M | sstate.s_ss.pssd.from_string = |
655 | 10.2M | ((pstate->s_options & SCAN_FROM_STRING) != 0) && |
656 | 10.2M | !level2_enabled; |
657 | 10.2M | s_PSSD_partially_init_inline(&sstate.s_ss.pssd); |
658 | 10.2M | sstate.s_ss.st.templat = &s_PSSD_template; |
659 | 10.2M | goto str; |
660 | 46.2M | case '{': |
661 | 46.2M | if (sstate.s_pstack == 0) { /* outermost procedure */ |
662 | 12.8M | 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 | 12.8M | sstate.s_pdepth = ref_stack_count_inline(&o_stack); |
668 | 12.8M | } |
669 | 46.2M | make_int(osp, sstate.s_pstack); |
670 | 46.2M | sstate.s_pstack = ref_stack_count_inline(&o_stack); |
671 | 46.2M | if_debug3m('S', imemory, "[S{]d=%d, s=%d->%d\n", |
672 | 46.2M | sstate.s_pdepth, (int)osp->value.intval, sstate.s_pstack); |
673 | 46.2M | goto snext; |
674 | 455k | case '>': |
675 | 455k | if (level2_enabled) { |
676 | 455k | ensure2(scanning_none); |
677 | 455k | sstate.s_ss.s_name.s_name_type = 0; |
678 | 455k | sstate.s_ss.s_name.s_try_number = false; |
679 | 455k | goto try_funny_name; |
680 | 455k | } |
681 | | /* falls through */ |
682 | 12 | case ')': |
683 | 12 | sreturn(gs_error_syntaxerror); |
684 | 46.0M | case '}': |
685 | 46.0M | if (sstate.s_pstack == 0) |
686 | 46.0M | sreturn(gs_error_syntaxerror); |
687 | 46.0M | osp--; |
688 | 46.0M | { |
689 | 46.0M | uint size = ref_stack_count_inline(&o_stack) - sstate.s_pstack; |
690 | 46.0M | ref arr; |
691 | | |
692 | 46.0M | if_debug4m('S', imemory, "[S}]d=%"PRIu32", s=%"PRIu32"->%"PRIpsint", c=%"PRIu32"\n", |
693 | 46.0M | sstate.s_pdepth, sstate.s_pstack, |
694 | 46.0M | (sstate.s_pstack == sstate.s_pdepth ? 0 : |
695 | 46.0M | ref_stack_index(&o_stack, size)->value.intval), |
696 | 46.0M | size + sstate.s_pstack); |
697 | 46.0M | if (size > max_array_size) |
698 | 46.0M | sreturn(gs_error_limitcheck); |
699 | 46.0M | myref = (sstate.s_pstack == sstate.s_pdepth ? pref : &arr); |
700 | 46.0M | if (check_only) { |
701 | 0 | make_empty_array(myref, 0); |
702 | 0 | ref_stack_pop(&o_stack, size); |
703 | 46.0M | } else if (ref_array_packing.value.boolval) { |
704 | 44.5M | retcode = make_packed_array(myref, &o_stack, size, |
705 | 44.5M | idmemory, "scanner(packed)"); |
706 | 44.5M | 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 | 44.5M | r_set_attrs(myref, a_executable); |
713 | 44.5M | } else { |
714 | 1.45M | retcode = ialloc_ref_array(myref, |
715 | 1.45M | a_executable + a_all, size, |
716 | 1.45M | "scanner(proc)"); |
717 | 1.45M | 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 | 1.45M | retcode = ref_stack_store(&o_stack, myref, size, 0, 1, |
724 | 1.45M | false, idmemory, "scanner"); |
725 | 1.45M | if (retcode < 0) { |
726 | 0 | ifree_ref_array(myref, "scanner(proc)"); |
727 | 0 | sreturn(retcode); |
728 | 0 | } |
729 | 1.45M | ref_stack_pop(&o_stack, size); |
730 | 1.45M | } |
731 | 46.0M | if (sstate.s_pstack == sstate.s_pdepth) { /* This was the top-level procedure. */ |
732 | 12.8M | spop1(); |
733 | 12.8M | sstate.s_pstack = 0; |
734 | 33.2M | } else { |
735 | 33.2M | if (osp < osbot) |
736 | 0 | ref_stack_pop_block(&o_stack); |
737 | 33.2M | sstate.s_pstack = osp->value.intval; |
738 | 33.2M | *osp = arr; |
739 | 33.2M | goto snext; |
740 | 33.2M | } |
741 | 46.0M | } |
742 | 12.8M | break; |
743 | 175M | case '/': |
744 | | /* |
745 | | * If the last thing in the input is a '/', don't try to read |
746 | | * any more data. |
747 | | */ |
748 | 175M | if (sptr >= endptr && s->end_status != EOFC) { |
749 | 36.7k | refill2(scanning_none); |
750 | 36.7k | } |
751 | 175M | c = sgetc_inline(s, sptr, endptr); |
752 | 175M | if (!PDFScanRules && (c == '/')) { |
753 | 16.5M | sstate.s_ss.s_name.s_name_type = 2; |
754 | 16.5M | c = sgetc_inline(s, sptr, endptr); |
755 | 16.5M | } else |
756 | 158M | sstate.s_ss.s_name.s_name_type = 1; |
757 | 175M | sstate.s_ss.s_name.s_try_number = false; |
758 | 175M | switch (decoder[c]) { |
759 | 19.4M | case ctype_name: |
760 | 175M | default: |
761 | 175M | goto do_name; |
762 | 175M | case ctype_btoken: |
763 | 72 | if (!(ref_binary_object_format.value.intval != 0 && level2_enabled)) |
764 | 0 | goto do_name; |
765 | | /* otherwise, an empty name */ |
766 | 97 | case ctype_exception: |
767 | 10.4k | 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 | 66.8k | case ctype_other: |
775 | 66.8k | if (c == ctrld) /* see above */ |
776 | 0 | goto do_name; |
777 | 66.8k | sstate.s_da.base = sstate.s_da.limit = daptr = 0; |
778 | 66.8k | sstate.s_da.is_dynamic = false; |
779 | 66.8k | goto nx; |
780 | 175M | } |
781 | 252k | case '%': |
782 | 252k | { /* Scan as much as possible within the buffer. */ |
783 | 252k | const byte *base = sptr; |
784 | 252k | const byte *end; |
785 | | |
786 | 2.40M | while (++sptr < endptr) /* stop 1 char early */ |
787 | 2.40M | switch (*sptr) { |
788 | 7.83k | case char_CR: |
789 | 7.83k | end = sptr; |
790 | 7.83k | if (sptr[1] == char_EOL) |
791 | 358 | sptr++; |
792 | 251k | cend: /* Check for externally processed comments. */ |
793 | 251k | retcode = scan_comment(i_ctx_p, myref, &sstate, |
794 | 251k | base, end, false); |
795 | 251k | if (retcode != 0) |
796 | 125k | goto comment; |
797 | 125k | goto top; |
798 | 241k | case char_EOL: |
799 | 243k | case '\f': |
800 | 243k | end = sptr; |
801 | 243k | goto cend; |
802 | 2.40M | } |
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 | 1.28k | --sptr; |
810 | 1.28k | sstate.s_da.buf[1] = 0; |
811 | 1.28k | { |
812 | | /* Could be an externally processable comment. */ |
813 | 1.28k | uint len = sptr + 1 - base; |
814 | 1.28k | if (len > sizeof(sstate.s_da.buf)) |
815 | 0 | len = sizeof(sstate.s_da.buf); |
816 | | |
817 | 1.28k | memcpy(sstate.s_da.buf, base, len); |
818 | 1.28k | daptr = sstate.s_da.buf + len; |
819 | 1.28k | } |
820 | 1.28k | sstate.s_da.base = sstate.s_da.buf; |
821 | 1.28k | sstate.s_da.is_dynamic = false; |
822 | 1.28k | } |
823 | | /* Enter here to continue scanning a comment. */ |
824 | | /* daptr must be set. */ |
825 | 185k | cont_comment:for (;;) { |
826 | 185k | switch ((c = sgetc_inline(s, sptr, endptr))) { |
827 | 184k | default: |
828 | 184k | if (c < 0) |
829 | 276 | 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 | 276 | 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 | 276 | goto end_comment; |
842 | 0 | default: |
843 | 0 | sreturn(gs_error_syntaxerror); |
844 | 276 | } |
845 | 184k | if (daptr < sstate.s_da.buf + max_comment_line) |
846 | 14.6k | *daptr++ = c; |
847 | 184k | continue; |
848 | 85 | case char_CR: |
849 | 853 | case char_EOL: |
850 | 1.00k | case '\f': |
851 | 1.28k | end_comment: |
852 | 1.28k | retcode = scan_comment(i_ctx_p, myref, &sstate, |
853 | 1.28k | sstate.s_da.buf, daptr, true); |
854 | 1.28k | if (retcode != 0) |
855 | 998 | goto comment; |
856 | 283 | goto top; |
857 | 185k | } |
858 | 185k | } |
859 | | /*NOTREACHED */ |
860 | 98.4k | case EOFC: |
861 | 98.4k | if (sstate.s_pstack != 0) { |
862 | 516 | if (check_only) |
863 | 0 | goto pause; |
864 | 516 | sreturn(gs_error_syntaxerror); |
865 | 0 | } |
866 | 97.9k | retcode = scan_EOF; |
867 | 97.9k | break; |
868 | 0 | case ERRC: |
869 | 0 | sreturn(gs_error_ioerror); |
870 | | |
871 | | /* Check for a Level 2 funny name (<< or >>). */ |
872 | | /* c is '<' or '>'. We already did an ensure2. */ |
873 | 949k | try_funny_name: |
874 | 949k | { |
875 | 949k | int c1 = sgetc_inline(s, sptr, endptr); |
876 | | |
877 | 949k | if (c1 == c) { |
878 | 949k | s1[0] = s1[1] = c; |
879 | 949k | name_ref(imemory, s1, 2, myref, 1); /* can't fail */ |
880 | 949k | goto have_name; |
881 | 949k | } |
882 | 10 | sputback_inline(s, sptr, endptr); |
883 | 10 | } |
884 | 10 | sreturn(gs_error_syntaxerror); |
885 | | |
886 | | /* Handle separately the names that might be a number. */ |
887 | 8.88M | case '0': |
888 | 100M | case '1': |
889 | 109M | case '2': |
890 | 116M | case '3': |
891 | 120M | case '4': |
892 | 121M | case '5': |
893 | 122M | case '6': |
894 | 123M | case '7': |
895 | 124M | case '8': |
896 | 125M | case '9': |
897 | 151M | case '.': |
898 | 151M | sign = 0; |
899 | 154M | 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 | 154M | retcode = scan_number(sptr + (sign & 1), |
907 | 154M | endptr /*(*endptr == char_CR ? endptr : endptr + 1) */ , |
908 | 154M | sign, myref, &newptr, i_ctx_p->scanner_options); |
909 | 154M | if (retcode == 1 && decoder[newptr[-1]] == ctype_space) { |
910 | 46.5M | sptr = newptr - 1; |
911 | 46.5M | if (*sptr == char_CR && sptr[1] == char_EOL) |
912 | 58 | sptr++; |
913 | 46.5M | retcode = 0; |
914 | 46.5M | ref_mark_new(myref); |
915 | 46.5M | break; |
916 | 46.5M | } |
917 | 108M | sstate.s_ss.s_name.s_name_type = 0; |
918 | 108M | sstate.s_ss.s_name.s_try_number = true; |
919 | 108M | goto do_name; |
920 | 198 | case '+': |
921 | 198 | sign = 1; |
922 | 198 | goto nr; |
923 | 3.12M | case '-': |
924 | 3.12M | sign = -1; |
925 | 3.12M | 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 | 3.12M | goto nr; |
951 | | |
952 | | /* Check for a binary object */ |
953 | 3.12M | case 128: case 129: case 130: case 131: case 132: case 133: case 134: case 135: |
954 | 43.4k | case 136: case 137: case 138: case 139: case 140: case 141: case 142: case 143: |
955 | 112k | case 144: case 145: case 146: case 147: case 148: case 149: case 150: case 151: |
956 | 112k | case 152: case 153: case 154: case 155: case 156: case 157: case 158: case 159: |
957 | 112k | if ((ref_binary_object_format.value.intval != 0 && level2_enabled)) { |
958 | 112k | s_end_inline(s, sptr, endptr); |
959 | 112k | retcode = scan_binary_token(i_ctx_p, myref, &sstate); |
960 | 112k | s_begin_inline(s, sptr, endptr); |
961 | 112k | if (retcode == scan_Refill) |
962 | 233 | goto pause; |
963 | 111k | break; |
964 | 112k | } |
965 | | /* Not a binary object, fall through. */ |
966 | | |
967 | | /* The default is a name. */ |
968 | 185k | default: |
969 | 185k | if (c < 0) { |
970 | 57.9k | dynamic_init(&sstate.s_da, name_memory(imemory)); /* sstate.s_da state must be clean */ |
971 | 57.9k | sstate.s_scan_type = scanning_none; |
972 | 57.9k | goto pause; |
973 | 57.9k | } |
974 | | /* Populate the switch with enough cases to force */ |
975 | | /* simple compilers to use a dispatch rather than tests. */ |
976 | 129k | case '!': |
977 | 217k | case '"': |
978 | 379k | case '#': |
979 | 1.38M | case '$': |
980 | 1.38M | case '&': |
981 | 1.45M | case '\'': |
982 | 1.45M | case '*': |
983 | 1.65M | case ',': |
984 | 4.14M | case '=': |
985 | 4.14M | case ':': |
986 | 6.06M | case ';': |
987 | 6.08M | case '?': |
988 | 6.08M | case '@': |
989 | 6.12M | case 'A': |
990 | 6.14M | case 'B': |
991 | 6.63M | case 'C': |
992 | 6.92M | case 'D': |
993 | 7.26M | case 'E': |
994 | 7.65M | case 'F': |
995 | 7.73M | case 'G': |
996 | 7.95M | case 'H': |
997 | 8.20M | case 'I': |
998 | 8.22M | case 'J': |
999 | 8.22M | case 'K': |
1000 | 8.26M | case 'L': |
1001 | 8.31M | case 'M': |
1002 | 9.24M | case 'N': |
1003 | 9.46M | case 'O': |
1004 | 10.0M | case 'P': |
1005 | 10.2M | case 'Q': |
1006 | 11.5M | case 'R': |
1007 | 12.1M | case 'S': |
1008 | 12.6M | case 'T': |
1009 | 12.7M | case 'U': |
1010 | 13.0M | case 'V': |
1011 | 13.2M | case 'W': |
1012 | 13.2M | case 'X': |
1013 | 13.2M | case 'Y': |
1014 | 13.2M | case 'Z': |
1015 | 13.2M | case '\\': |
1016 | 13.2M | case '^': |
1017 | 13.2M | case '_': |
1018 | 13.2M | case '`': |
1019 | 19.0M | case 'a': |
1020 | 22.2M | case 'b': |
1021 | 35.6M | case 'c': |
1022 | 68.1M | case 'd': |
1023 | 97.9M | case 'e': |
1024 | 104M | case 'f': |
1025 | 116M | case 'g': |
1026 | 116M | case 'h': |
1027 | 147M | case 'i': |
1028 | 147M | case 'j': |
1029 | 150M | case 'k': |
1030 | 156M | case 'l': |
1031 | 159M | case 'm': |
1032 | 165M | case 'n': |
1033 | 167M | case 'o': |
1034 | 194M | case 'p': |
1035 | 194M | case 'q': |
1036 | 203M | case 'r': |
1037 | 216M | case 's': |
1038 | 219M | case 't': |
1039 | 220M | case 'u': |
1040 | 220M | case 'v': |
1041 | 222M | case 'w': |
1042 | 222M | case 'x': |
1043 | 222M | case 'y': |
1044 | 222M | case 'z': |
1045 | 222M | case '|': |
1046 | 222M | case '~': |
1047 | 222M | 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 | 222M | sstate.s_ss.s_name.s_name_type = 0; |
1053 | 222M | sstate.s_ss.s_name.s_try_number = false; |
1054 | 506M | 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 | 506M | sstate.s_da.base = (byte *) sptr; |
1059 | 506M | sstate.s_da.is_dynamic = false; |
1060 | 506M | { |
1061 | 506M | const byte *endp1 = endptr - 1; |
1062 | | |
1063 | 3.79G | do { |
1064 | 3.79G | if (sptr >= endp1) /* stop 1 early! */ |
1065 | 660k | goto dyn_name; |
1066 | 3.79G | } |
1067 | 3.79G | while (decoder[*++sptr] <= max_name_ctype || *sptr == ctrld); /* digit or name */ |
1068 | 506M | } |
1069 | | /* Name ended within the buffer. */ |
1070 | 505M | daptr = (byte *) sptr; |
1071 | 505M | c = *sptr; |
1072 | 505M | goto nx; |
1073 | 660k | dyn_name: /* Name extended past end of buffer. */ |
1074 | 660k | 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 | 660k | sstate.s_da.limit = (byte *)++ sptr; |
1079 | 660k | sstate.s_da.memory = name_memory(imemory); |
1080 | 660k | retcode = dynamic_grow(&sstate.s_da, sstate.s_da.limit, name_max_string); |
1081 | 660k | if (retcode < 0) { |
1082 | 2 | dynamic_save(&sstate.s_da); |
1083 | 2 | if (retcode != gs_error_VMerror) |
1084 | 2 | sreturn(retcode); |
1085 | 0 | sstate.s_scan_type = scanning_name; |
1086 | 0 | goto pause_ret; |
1087 | 2 | } |
1088 | 660k | daptr = sstate.s_da.next; |
1089 | | /* Enter here to continue scanning a name. */ |
1090 | | /* daptr must be set. */ |
1091 | 709k | cont_name:s_begin_inline(s, sptr, endptr); |
1092 | 2.74M | while (decoder[c = sgetc_inline(s, sptr, endptr)] <= max_name_ctype || c == ctrld) { |
1093 | 2.03M | if (daptr == sstate.s_da.limit) { |
1094 | 11.9k | retcode = dynamic_grow(&sstate.s_da, daptr, |
1095 | 11.9k | name_max_string); |
1096 | 11.9k | if (retcode < 0) { |
1097 | 4 | dynamic_save(&sstate.s_da); |
1098 | 4 | if (retcode != gs_error_VMerror) |
1099 | 4 | sreturn(retcode); |
1100 | 0 | sputback_inline(s, sptr, endptr); |
1101 | 0 | sstate.s_scan_type = scanning_name; |
1102 | 0 | goto pause_ret; |
1103 | 4 | } |
1104 | 11.9k | daptr = sstate.s_da.next; |
1105 | 11.9k | } |
1106 | 2.03M | *daptr++ = c; |
1107 | 2.03M | } |
1108 | 506M | nx:switch (decoder[c]) { |
1109 | 287M | case ctype_other: |
1110 | 287M | if (c == ctrld) /* see above */ |
1111 | 0 | break; |
1112 | 287M | case ctype_btoken: |
1113 | 287M | sputback_inline(s, sptr, endptr); |
1114 | 287M | break; |
1115 | 219M | case ctype_space: |
1116 | | /* Check for \r\n */ |
1117 | 219M | if (c == char_CR) { |
1118 | 95.8k | 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 | 108 | if (s->end_status != EOFC) { |
1122 | 101 | sptr--; |
1123 | 101 | goto pause_name; |
1124 | 101 | } |
1125 | 95.7k | } else if (sptr[1] == char_EOL) |
1126 | 1.76k | sptr++; |
1127 | 95.8k | } |
1128 | 219M | break; |
1129 | 219M | case ctype_exception: |
1130 | 350k | switch (c) { |
1131 | 0 | case INTC: |
1132 | 48.3k | case CALLC: |
1133 | 48.3k | goto pause_name; |
1134 | 0 | case ERRC: |
1135 | 0 | sreturn(gs_error_ioerror); |
1136 | 302k | case EOFC: |
1137 | 302k | break; |
1138 | 350k | } |
1139 | 506M | } |
1140 | | /* Check for a number */ |
1141 | 506M | if (sstate.s_ss.s_name.s_try_number) { |
1142 | 108M | const byte *base = sstate.s_da.base; |
1143 | | |
1144 | 108M | scan_sign(sign, base); |
1145 | 108M | retcode = scan_number(base, daptr, sign, myref, &newptr, i_ctx_p->scanner_options); |
1146 | 108M | if (retcode == 1) { |
1147 | 73.2k | ref_mark_new(myref); |
1148 | 73.2k | retcode = 0; |
1149 | 108M | } else if (retcode != gs_error_syntaxerror) { |
1150 | 81.7M | dynamic_free(&sstate.s_da); |
1151 | 81.7M | if (sstate.s_ss.s_name.s_name_type == 2) |
1152 | 81.7M | sreturn(gs_error_syntaxerror); |
1153 | 81.7M | break; /* might be gs_error_limitcheck */ |
1154 | 81.7M | } |
1155 | 108M | } |
1156 | 424M | if (sstate.s_da.is_dynamic) { /* We've already allocated the string on the heap. */ |
1157 | 455k | uint size = daptr - sstate.s_da.base; |
1158 | | |
1159 | 455k | retcode = name_ref(imemory, sstate.s_da.base, size, myref, -1); |
1160 | 455k | if (retcode >= 0) { |
1161 | 399k | dynamic_free(&sstate.s_da); |
1162 | 399k | } else { |
1163 | 55.5k | retcode = dynamic_resize(&sstate.s_da, size); |
1164 | 55.5k | 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 | 55.5k | retcode = name_ref(imemory, sstate.s_da.base, size, myref, 2); |
1171 | 55.5k | } |
1172 | 424M | } else { |
1173 | 424M | retcode = name_ref(imemory, sstate.s_da.base, (uint) (daptr - sstate.s_da.base), |
1174 | 424M | myref, !s->foreign); |
1175 | 424M | } |
1176 | | /* Done scanning. Check for preceding /'s. */ |
1177 | 424M | 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 | 425M | have_name:switch (sstate.s_ss.s_name.s_name_type) { |
1190 | 250M | case 0: /* ordinary executable name */ |
1191 | 250M | if (r_has_type(myref, t_name)) /* i.e., not a number */ |
1192 | 250M | r_set_attrs(myref, a_executable); |
1193 | 409M | case 1: /* quoted name */ |
1194 | 409M | break; |
1195 | 16.5M | case 2: /* immediate lookup */ |
1196 | 16.5M | { |
1197 | 16.5M | ref *pvalue; |
1198 | | |
1199 | 16.5M | if (!r_has_type(myref, t_name) || |
1200 | 16.5M | (pvalue = dict_find_name(myref)) == 0) { |
1201 | 6 | ref_assign(&sstate.s_error.object, myref); |
1202 | 6 | r_set_attrs(&sstate.s_error.object, |
1203 | 6 | a_executable); /* Adobe compatibility */ |
1204 | 6 | sreturn(gs_error_undefined); |
1205 | 0 | } |
1206 | 16.5M | if (sstate.s_pstack != 0 && |
1207 | 16.5M | r_space(pvalue) > ialloc_space(idmemory) |
1208 | 16.5M | ) |
1209 | 16.5M | sreturn(gs_error_invalidaccess); |
1210 | 16.5M | ref_assign_new(myref, pvalue); |
1211 | 16.5M | } |
1212 | 425M | } |
1213 | 741M | } |
1214 | 657M | sret:if (retcode < 0) { |
1215 | 1.49k | s_end_inline(s, sptr, endptr); |
1216 | 1.49k | pstate->s_error = sstate.s_error; |
1217 | 1.49k | if (sstate.s_pstack != 0) { |
1218 | 636 | if (retcode == gs_error_undefined) |
1219 | 3 | *pref = *osp; /* return undefined name as error token */ |
1220 | 636 | ref_stack_pop(&o_stack, |
1221 | 636 | ref_stack_count(&o_stack) - (sstate.s_pdepth - 1)); |
1222 | 636 | } |
1223 | 1.49k | return retcode; |
1224 | 1.49k | } |
1225 | | /* If we are at the top level, return the object, */ |
1226 | | /* otherwise keep going. */ |
1227 | 657M | if (sstate.s_pstack == 0) { |
1228 | 356M | s_end_inline(s, sptr, endptr); |
1229 | 356M | return retcode; |
1230 | 356M | } |
1231 | 380M | snext:if_not_spush1() { |
1232 | 1 | s_end_inline(s, sptr, endptr); |
1233 | 1 | sstate.s_scan_type = scanning_none; |
1234 | 1 | goto save; |
1235 | 1 | } |
1236 | 380M | myref = osp; |
1237 | 380M | goto top; |
1238 | | |
1239 | | /* Pause for an interrupt or callout. */ |
1240 | 48.4k | 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 | 48.4k | sstate.s_da.next = daptr; |
1244 | 48.4k | dynamic_save(&sstate.s_da); |
1245 | 48.4k | sstate.s_scan_type = scanning_name; |
1246 | 143k | pause: |
1247 | 143k | retcode = scan_Refill; |
1248 | 143k | pause_ret: |
1249 | 143k | s_end_inline(s, sptr, endptr); |
1250 | 143k | suspend: |
1251 | 143k | if (sstate.s_pstack != 0) |
1252 | 554 | osp--; /* myref */ |
1253 | 270k | save: |
1254 | 270k | *pstate = sstate; |
1255 | 270k | return retcode; |
1256 | | |
1257 | | /* Handle a scanned comment. */ |
1258 | 126k | comment: |
1259 | 126k | if (retcode < 0) |
1260 | 0 | goto sret; |
1261 | 126k | s_end_inline(s, sptr, endptr); |
1262 | 126k | sstate.s_scan_type = scanning_none; |
1263 | 126k | goto save; |
1264 | 126k | } |