/* <obj1> ... <objn> <n> .execn - */ static int zexecn(i_ctx_t *i_ctx_p) { os_ptr op = osp; uint n, i; es_ptr esp_orig; check_int_leu(*op, max_uint - 1); n = (uint) op->value.intval; check_op(n + 1); check_estack(n); esp_orig = esp; for (i = 0; i < n; ++i) { const ref *rp = ref_stack_index(&o_stack, (long)(i + 1)); /* Make sure this object is legal to execute. */ if (ref_type_uses_access(r_type(rp))) { if (!r_has_attr(rp, a_execute) && r_has_attr(rp, a_executable) ) { esp = esp_orig; return_error(e_invalidaccess); } } /* Executable nulls have a special meaning on the e-stack, */ /* so since they are no-ops, don't push them. */ if (!r_has_type_attrs(rp, t_null, a_executable)) { ++esp; ref_assign(esp, rp); } } esfile_check_cache(); pop(n + 1); return o_push_estack; }
/* * Continuation for procedure data source. We use the topmost aliasing slot * to remember whether we've just called the procedure (1) or whether we're * returning from a RemapColor callout (0). */ static int image_proc_continue(i_ctx_t *i_ctx_p) { os_ptr op = osp; gs_image_enum *penum = r_ptr(esp, gs_image_enum); int px = ETOP_PLANE_INDEX(esp)->value.intval; int num_sources = ETOP_NUM_SOURCES(esp)->value.intval; uint size, used[gs_image_max_planes]; gs_const_string plane_data[gs_image_max_planes]; const byte *wanted; int i, code; if (!r_has_type_attrs(op, t_string, a_read)) { check_op(1); /* Procedure didn't return a (readable) string. Quit. */ esp = zimage_pop_estack(esp); image_cleanup(i_ctx_p); return_error(!r_has_type(op, t_string) ? e_typecheck : e_invalidaccess); } size = r_size(op); if (size == 0 && ETOP_SOURCE(esp, 0)[1].value.intval == 0) code = 1; else { for (i = 0; i < num_sources; i++) plane_data[i].size = 0; plane_data[px].data = op->value.bytes; plane_data[px].size = size; code = gs_image_next_planes(penum, plane_data, used); if (code == e_RemapColor) { op->value.bytes += used[px]; /* skip used data */ r_dec_size(op, used[px]); ETOP_SOURCE(esp, 0)[1].value.intval = 0; /* RemapColor callout */ return code; } } if (code) { /* Stop now. */ esp = zimage_pop_estack(esp); pop(1); image_cleanup(i_ctx_p); return (code < 0 ? code : o_pop_estack); } pop(1); wanted = gs_image_planes_wanted(penum); do { if (++px == num_sources) px = 0; } while (!wanted[px]); ETOP_PLANE_INDEX(esp)->value.intval = px; return image_proc_process(i_ctx_p); }
/* r_size(op1) was set just above. */ static int do_execstack(i_ctx_t *i_ctx_p, bool include_marks, os_ptr op1) { os_ptr op = osp; ref *arefs = op1->value.refs; uint asize = r_size(op1); uint i; ref *rq; /* * Copy elements from the stack to the array, * optionally skipping executable nulls. * Clear the executable bit in any internal operators, and * convert t_structs and t_astructs (which can only appear * in connection with stack marks, which means that they will * probably be freed when unwinding) to something harmless. */ for (i = 0, rq = arefs + asize; rq != arefs; ++i) { const ref *rp = ref_stack_index(&e_stack, (long)i); if (r_has_type_attrs(rp, t_null, a_executable) && !include_marks) continue; --rq; ref_assign_old(op1, rq, rp, "execstack"); switch (r_type(rq)) { case t_operator: { uint opidx = op_index(rq); if (opidx == 0 || op_def_is_internal(op_index_def(opidx))) r_clear_attrs(rq, a_executable); break; } case t_struct: case t_astruct: { const char *tname = rq->value.pstruct ? gs_struct_type_name_string( gs_object_type(imemory, rq->value.pstruct)) : "NULL"; make_const_string(rq, a_readonly | avm_foreign, strlen(tname), (const byte *)tname); break; } default: ; } } pop(op - op1); return 0; }
/* * Count the number of elements on the exec stack, with or without * the normally invisible elements (*op is a Boolean that indicates this). */ static uint count_exec_stack(i_ctx_t *i_ctx_p, bool include_marks) { uint count = ref_stack_count(&e_stack); if (!include_marks) { uint i; for (i = count; i--;) if (r_has_type_attrs(ref_stack_index(&e_stack, (long)i), t_null, a_executable)) --count; } return count; }
/* Get the current file from which the interpreter is reading. */ static ref * zget_current_file(i_ctx_t *i_ctx_p) { ref_stack_enum_t rsenum; ref_stack_enum_begin(&rsenum, &e_stack); do { uint count = rsenum.size; es_ptr ep = rsenum.ptr + count - 1; for (; count; count--, ep--) if (r_has_type_attrs(ep, t_file, a_executable)) return ep; } while (ref_stack_enum_next(&rsenum)); return 0; }
/* * If a PostScript object is a Function procedure, return the function * object, otherwise return 0. */ gs_function_t * ref_function(const ref *op) { if (r_has_type(op, t_array) && r_has_masked_attrs(op, a_executable | a_execute, a_executable | a_all) && r_size(op) == 2 && r_has_type_attrs(op->value.refs + 1, t_operator, a_executable) && op->value.refs[1].value.opproc == zexecfunction && r_is_struct(op->value.refs) && r_has_masked_attrs(op->value.refs, a_executable | a_execute, a_executable | a_all) ) return (gs_function_t *)op->value.refs->value.pstruct; return 0; }
/* <array> dictstack <subarray> */ static int zdictstack(i_ctx_t *i_ctx_p) { os_ptr op = osp; uint count = ref_stack_count(&d_stack); if (!level2_enabled) count--; /* see dstack.h */ if (!r_is_array(op)) return_op_typecheck(op); if (r_size(op) < count) return_error(e_rangecheck); if (!r_has_type_attrs(op, t_array, a_write)) return_error(e_invalidaccess); return ref_stack_store(&d_stack, op, count, 0, 0, true, idmemory, "dictstack"); }
/* <obj_0> ... <obj_n-1> <array> astore <array> */ static int zastore(i_ctx_t *i_ctx_p) { os_ptr op = osp; uint size; int code; if (!r_is_array(op)) return_op_typecheck(op); size = r_size(op); /* Amazingly, the following is valid: 0 array noaccess astore */ if (size == 0) return 0; if (!r_has_type_attrs(op, t_array, a_write)) return_error(gs_error_invalidaccess); if (size > op - osbot) { /* The store operation might involve other stack segments. */ ref arr; if (size >= ref_stack_count(&o_stack)) return_error(gs_error_stackunderflow); arr = *op; code = ref_stack_store(&o_stack, &arr, size, 1, 0, true, idmemory, "astore"); if (code < 0) return code; ref_stack_pop(&o_stack, size); *ref_stack_index(&o_stack, 0) = arr; } else { code = refcpy_to_old(op, 0, op - size, size, idmemory, "astore"); if (code < 0) return code; op[-(int)size] = *op; pop(size); } return 0; }