/* its length; nothing else has been checked. */ static int copy_interval(i_ctx_t *i_ctx_p /* for ref_assign_old */, os_ptr prto, uint index, os_ptr prfrom, client_name_t cname) { int fromtype = r_type(prfrom); uint fromsize = r_size(prfrom); if (!(fromtype == r_type(prto) || ((fromtype == t_shortarray || fromtype == t_mixedarray) && r_type(prto) == t_array)) ) return_op_typecheck(prfrom); check_read(*prfrom); check_write(*prto); if (fromsize > r_size(prto) - index) return_error(e_rangecheck); switch (fromtype) { case t_array: { /* We have to worry about aliasing, */ /* but refcpy_to_old takes care of it for us. */ return refcpy_to_old(prto, index, prfrom->value.refs, fromsize, idmemory, cname); } case t_string: { /* memmove takes care of aliasing. */ memmove(prto->value.bytes + index, prfrom->value.bytes, fromsize); } break; case t_mixedarray: case t_shortarray: { /* We don't have to worry about aliasing, because */ /* packed arrays are read-only and hence the destination */ /* can't be a packed array. */ uint i; const ref_packed *packed = prfrom->value.packed; ref *pdest = prto->value.refs + index; ref elt; for (i = 0; i < fromsize; i++, pdest++) { packed_get(imemory, packed, &elt); ref_assign_old(prto, pdest, &elt, cname); packed = packed_next(packed); } } break; } return 0; }
/* <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; }