/* Free the image enumerator. */ void gx_image_free_enum(gx_image_enum_common_t **ppenum) { gx_image_enum_common_t * penum = *ppenum; gs_memory_t *mem = penum->memory; /* Bug 688845 comment #38 : Adobe Illustrator creates a Postscript document, in which an image data procedure executes 'save', and the corresponding 'restore' appears after the image end. It causes this procedure is called at a higher save level than at which the enumerator was allocated, so that gs_free_object below works idle. Nevertheless we can't leave pointers in the structure, because they may point to blocks already released by the client's subclass method for end_image. Leaving them uncleaned caused a real crash in the garbager - see bug 688845. So we clean the entire subclassed enumerator here, rather this is a generic function for base class. Note the cleaning is neccessaryfor Postscript only, because other languaged don't implement save-restore. */ memset(penum, 0, gs_object_size(mem, penum)); gs_free_object(mem, penum, "gx_image_free_enum"); *ppenum = NULL; }
/* <array|dict|name|packedarray|string> length <int> */ static int zlength(i_ctx_t *i_ctx_p) { os_ptr op = osp; switch (r_type(op)) { case t_array: case t_string: case t_mixedarray: case t_shortarray: check_read(*op); make_int(op, r_size(op)); return 0; case t_dictionary: check_dict_read(*op); make_int(op, dict_length(op)); return 0; case t_name: { ref str; name_string_ref(imemory, op, &str); make_int(op, r_size(&str)); return 0; } case t_astruct: if (gs_object_type(imemory, op->value.pstruct) != &st_bytes) return_error(e_typecheck); check_read(*op); make_int(op, gs_object_size(imemory, op->value.pstruct)); return 0; default: return_op_typecheck(op); } }
/* we call this from ps code to instantiate a jbig2_global_context object which the JBIG2Decode filter uses if available. The pointer to the global context is stored in an astruct object and returned that way since it lives outside the interpreters memory management */ static int z_jbig2makeglobalctx(i_ctx_t * i_ctx_p) { void *global = NULL; s_jbig2_global_data_t *st; os_ptr op = osp; byte *data; int size; int code = 0; check_type(*op, t_astruct); size = gs_object_size(imemory, op->value.pstruct); data = r_ptr(op, byte); code = s_jbig2decode_make_global_data(data, size, &global); if (size > 0 && global == NULL) { dlprintf("failed to create parsed JBIG2GLOBALS object."); return_error(e_unknownerror); } st = ialloc_struct(s_jbig2_global_data_t, &st_jbig2_global_data_t, "jbig2decode parsed global context"); if (st == NULL) return_error(e_VMerror); st->data = global; make_astruct(op, a_readonly | icurrent_space, (byte*)st); return code; }
/* Add a command to the DL table - pen up or pen down coordinates. Resizing the table as appropriate. */ static int hpgl_add_dl_char_data(hpgl_state_t * pgls, hpgl_dl_cdata_t * pcdata, short cc_data) { /* characters stored as short */ int csz = sizeof(short); if (pcdata->index == -1) { /* first element - allocate a small array which will be resized as needed */ pcdata->data = (short *)gs_alloc_bytes(pgls->memory, 2 * csz, "DL data"); if (pcdata->data == 0) return e_Memory; } else if (gs_object_size(pgls->memory, pcdata->data) == (pcdata->index + 1) * csz) { /* new character doesn't fit - double the size of the array */ short *new_cdata = (short *)gs_resize_object(pgls->memory, pcdata->data, (pcdata->index + 1) * csz * 2, "DL data resize"); if (new_cdata == 0) { return e_Memory; } pcdata->data = new_cdata; } pcdata->data[++pcdata->index] = cc_data; return 0; }
/* <string> <index> <int> put - */ static int zput(i_ctx_t *i_ctx_p) { os_ptr op = osp; os_ptr op1 = op - 1; os_ptr op2 = op1 - 1; byte *sdata; uint ssize; switch (r_type(op2)) { case t_dictionary: if (i_ctx_p->in_superexec == 0) check_dict_write(*op2); { int code = idict_put(op2, op1, op); if (code < 0) return code; /* error */ } break; case t_array: check_write(*op2); check_int_ltu(*op1, r_size(op2)); store_check_dest(op2, op); { ref *eltp = op2->value.refs + (uint) op1->value.intval; ref_assign_old(op2, eltp, op, "put"); } break; case t_mixedarray: /* packed arrays are read-only */ case t_shortarray: return_error(e_invalidaccess); case t_string: sdata = op2->value.bytes; ssize = r_size(op2); str: check_write(*op2); check_int_ltu(*op1, ssize); check_int_leu(*op, 0xff); sdata[(uint)op1->value.intval] = (byte)op->value.intval; break; case t_astruct: if (gs_object_type(imemory, op2->value.pstruct) != &st_bytes) return_error(e_typecheck); sdata = r_ptr(op2, byte); ssize = gs_object_size(imemory, op2->value.pstruct); goto str; default: return_op_typecheck(op2); } pop(3); return 0; }
/* BitsPerSample. */ static int dict_threshold2_params(const ref * pdict, gs_threshold2_halftone * ptp, ref * ptproc, gs_memory_t *mem) { ref *tstring; int code = dict_threshold_common_params(pdict, (gs_threshold_halftone_common *)ptp, &tstring, ptproc); int bps; uint size; int cw2, ch2; if (code < 0 || (code = cw2 = dict_int_param(pdict, "Width2", 0, 0x7fff, 0, &ptp->width2)) < 0 || (code = ch2 = dict_int_param(pdict, "Height2", 0, 0x7fff, 0, &ptp->height2)) < 0 || (code = dict_int_param(pdict, "BitsPerSample", 8, 16, -1, &bps)) < 0 ) return code; if ((bps != 8 && bps != 16) || cw2 != ch2 || (!cw2 && (ptp->width2 == 0 || ptp->height2 == 0)) ) return_error(e_rangecheck); ptp->bytes_per_sample = bps / 8; switch (r_type(tstring)) { case t_string: size = r_size(tstring); gs_bytestring_from_string(&ptp->thresholds, tstring->value.const_bytes, size); break; case t_astruct: if (gs_object_type(mem, tstring->value.pstruct) != &st_bytes) return_error(e_typecheck); size = gs_object_size(mem, tstring->value.pstruct); gs_bytestring_from_bytes(&ptp->thresholds, r_ptr(tstring, byte), 0, size); break; default: return_error(e_typecheck); } check_read(*tstring); if (size != (ptp->width * ptp->height + ptp->width2 * ptp->height2) * ptp->bytes_per_sample) return_error(e_rangecheck); return 0; }
/* <bytestring1> <index> <string2> putinterval - */ static int zputinterval(i_ctx_t *i_ctx_p) { os_ptr op = osp; os_ptr opindex = op - 1; os_ptr opto = opindex - 1; int code; switch (r_type(opto)) { default: return_error(e_typecheck); case t__invalid: if (r_type(op) != t_array && r_type(op) != t_string && r_type(op) != t__invalid) return_error(e_typecheck); /* to match Distiller */ else return_error(e_stackunderflow); case t_mixedarray: case t_shortarray: return_error(e_invalidaccess); case t_array: case t_string: check_write(*opto); check_int_leu(*opindex, r_size(opto)); code = copy_interval(i_ctx_p, opto, (uint)(opindex->value.intval), op, "putinterval"); break; case t_astruct: { uint dsize, ssize, index; check_write(*opto); if (gs_object_type(imemory, opto->value.pstruct) != &st_bytes) return_error(e_typecheck); dsize = gs_object_size(imemory, opto->value.pstruct); check_int_leu(*opindex, dsize); index = (uint)opindex->value.intval; check_read_type(*op, t_string); ssize = r_size(op); if (ssize > dsize - index) return_error(e_rangecheck); memcpy(r_ptr(opto, byte) + index, op->value.const_bytes, ssize); code = 0; break; } } if (code >= 0) pop(3); return code; }
/* Read a string value. */ static int ref_param_read_string_value(gs_memory_t *mem, const iparam_loc * ploc, gs_param_string * pvalue) { const ref *pref = ploc->pvalue; switch (r_type(pref)) { case t_name: { ref nref; name_string_ref(mem, pref, &nref); pvalue->data = nref.value.const_bytes; pvalue->size = r_size(&nref); pvalue->persistent = true; } break; case t_string: iparam_check_read(*ploc); pvalue->data = pref->value.const_bytes; pvalue->size = r_size(pref); pvalue->persistent = false; break; case t_astruct: /* Note: technically, instead of the "mem" argument, we should be using the plists's ref_memory. However, in a simple call to .putdeviceparams, they are identical. */ iparam_check_read(*ploc); if (gs_object_type(mem, pref->value.pstruct) != &st_bytes) return iparam_note_error(*ploc, e_typecheck); pvalue->data = r_ptr(pref, byte); pvalue->size = gs_object_size(mem, pref->value.pstruct); pvalue->persistent = false; break; default: return iparam_note_error(*ploc, e_typecheck); } return 0; }
static void * gs_heap_resize_object(gs_memory_t * mem, void *obj, uint new_num_elements, client_name_t cname) { gs_malloc_memory_t *mmem = (gs_malloc_memory_t *) mem; gs_malloc_block_t *ptr = (gs_malloc_block_t *) obj - 1; gs_memory_type_ptr_t pstype = ptr->type; uint old_size = gs_object_size(mem, obj) + sizeof(gs_malloc_block_t); uint new_size = gs_struct_type_size(pstype) * new_num_elements + sizeof(gs_malloc_block_t); gs_malloc_block_t *new_ptr; if (new_size == old_size) return obj; if (mmem->monitor) gx_monitor_enter(mmem->monitor); /* Exclusive access */ new_ptr = (gs_malloc_block_t *) gs_realloc(ptr, old_size, new_size); if (new_ptr == 0) return 0; if (new_ptr->prev) new_ptr->prev->next = new_ptr; else mmem->allocated = new_ptr; if (new_ptr->next) new_ptr->next->prev = new_ptr; new_ptr->size = new_size - sizeof(gs_malloc_block_t); mmem->used -= old_size; mmem->used += new_size; if (mmem->monitor) gx_monitor_leave(mmem->monitor); /* Done with exclusive access */ if (new_size > old_size) gs_alloc_fill((byte *) new_ptr + old_size, gs_alloc_fill_alloc, new_size - old_size); return new_ptr + 1; }
static int zreusablestream(i_ctx_t *i_ctx_p) { os_ptr op = osp; os_ptr source_op = op - 1; long length = max_long; bool close_source; int code; check_type(*op, t_boolean); close_source = op->value.boolval; if (r_has_type(source_op, t_string)) { uint size = r_size(source_op); check_read(*source_op); code = make_rss(i_ctx_p, source_op, source_op->value.const_bytes, size, r_space(source_op), 0L, size, false); } else if (r_has_type(source_op, t_astruct)) { uint size = gs_object_size(imemory, source_op->value.pstruct); if (gs_object_type(imemory, source_op->value.pstruct) != &st_bytes) return_error(e_rangecheck); check_read(*source_op); code = make_rss(i_ctx_p, source_op, (const byte *)source_op->value.pstruct, size, r_space(source_op), 0L, size, true); } else if (r_has_type(source_op, t_array)) { /* no packedarrays */ int i, blk_cnt, blk_sz; ref *blk_ref; ulong filelen = 0; check_read(*source_op); blk_cnt = r_size(source_op); blk_ref = source_op->value.refs; if (blk_cnt > 0) { blk_sz = r_size(blk_ref); for (i = 0; i < blk_cnt; i++) { int len; check_read_type(blk_ref[i], t_string); len = r_size(&blk_ref[i]); if (len > blk_sz || (len < blk_sz && i < blk_cnt - 1)) return_error(e_rangecheck); /* last block can be smaller */ filelen += len; } } if (filelen == 0) { code = make_rss(i_ctx_p, source_op, (unsigned char *)"", 0, r_space(source_op), 0, 0, false); } else { code = make_aos(i_ctx_p, source_op, blk_sz, r_size(&blk_ref[blk_cnt - 1]), filelen); } } else { long offset = 0; stream *source; stream *s; check_read_file(i_ctx_p, source, source_op); s = source; rs: if (s->cbuf_string.data != 0) { /* string stream */ long pos = stell(s); long avail = sbufavailable(s) + pos; offset += pos; code = make_rss(i_ctx_p, source_op, s->cbuf_string.data, s->cbuf_string.size, imemory_space((const gs_ref_memory_t *)s->memory), offset, min(avail, length), false); } else if (s->file != 0) { /* file stream */ if (~s->modes & (s_mode_read | s_mode_seek)) return_error(e_ioerror); code = make_rfs(i_ctx_p, source_op, s, offset + stell(s), length); } else if (s->state->templat == &s_SFD_template) { /* SubFileDecode filter */ const stream_SFD_state *const sfd_state = (const stream_SFD_state *)s->state; if (sfd_state->eod.size != 0) return_error(e_rangecheck); offset += sfd_state->skip_count - sbufavailable(s); if (sfd_state->count != 0) { long left = max(sfd_state->count, 0) + sbufavailable(s); if (left < length) length = left; } s = s->strm; goto rs; } else /* some other kind of stream */ return_error(e_rangecheck); if (close_source) { stream *rs = fptr(source_op); rs->strm = source; /* only for close_source */ rs->close_strm = true; } } if (code >= 0) pop(1); return code; }