Ejemplo n.º 1
0
/* Only the type of *op has been checked. */
int
zcopy_dict(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    os_ptr op1 = op - 1;
    int code;

    check_type(*op1, t_dictionary);
    check_dict_read(*op1);
    check_dict_write(*op);
    if (!imemory->gs_lib_ctx->dict_auto_expand &&
	(dict_length(op) != 0 || dict_maxlength(op) < dict_length(op1))
	)
	return_error(e_rangecheck);
    code = idict_copy(op1, op);
    if (code < 0)
	return code;
    /*
     * In Level 1 systems, we must copy the access attributes too.
     * The only possible effect this can have is to make the
     * copy read-only if the original dictionary is read-only.
     */
    if (!level2_enabled)
	r_copy_attrs(dict_access_ref(op), a_write, dict_access_ref(op1));
    ref_assign(op1, op);
    pop(1);
    return 0;
}
Ejemplo n.º 2
0
/* or if the object did not have the access already when modify=1. */
static int
access_check(i_ctx_t *i_ctx_p,
	     int access,	/* mask for attrs */
	     bool modify)	/* if true, reduce access */
{
    os_ptr op = osp;
    ref *aop;

    switch (r_type(op)) {
	case t_dictionary:
	    aop = dict_access_ref(op);
	    if (modify) {
		if (!r_has_attrs(aop, access))
		    return_error(e_invalidaccess);
		ref_save(op, aop, "access_check(modify)");
		r_clear_attrs(aop, a_all);
		r_set_attrs(aop, access);
		dict_set_top();
		return 0;
	    }
	    break;
	case t_array:
	case t_file:
	case t_string:
	case t_mixedarray:
	case t_shortarray:
	case t_astruct:
	case t_device:;
	    if (modify) {
		if (!r_has_attrs(op, access))
		    return_error(e_invalidaccess);
		r_clear_attrs(op, a_all);
		r_set_attrs(op, access);
		return 0;
	    }
	    aop = op;
	    break;
	default:
	    return_op_typecheck(op);
    }
    return (r_has_attrs(aop, access) ? 1 : 0);
}
Ejemplo n.º 3
0
/* <obj:array|packedarray|dict|file|string> noaccess <obj> */
static int
znoaccess(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;

    check_op(1);
    if (r_has_type(op, t_dictionary)) {
	ref *aop = dict_access_ref(op);
	
	/* CPSI throws invalidaccess when seting noaccess to a readonly dictionary (CET 13-13-6) : */
	if (!r_has_attrs(aop, a_write)) {
	    if (!r_has_attrs(aop, a_read) && !r_has_attrs(aop, a_execute)) {
		/* Already noaccess - do nothing (CET 24-09-1). */
		return 0;
	    }
	    return_error(e_invalidaccess);
	}

	/* Don't allow removing read access to permanent dictionaries. */
	if (dict_is_permanent_on_dstack(op))
	    return_error(e_invalidaccess);
    }
    return access_check(i_ctx_p, 0, true);
}
Ejemplo n.º 4
0
static int
zmatchmedia(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    os_ptr preq = op - 3;
    os_ptr pattr = op - 2;
    os_ptr ppol = op - 1;
    os_ptr pkeys = op;		/* *const */
    int policy_default;
    float best_mismatch = (float)max_long;	/* adhoc */
    float mepos_penalty;
    float mbest = best_mismatch;
    match_record_t match;
    ref no_priority;
    ref *ppriority;
    int mepos, orient;
    bool roll;
    int code;
    int ai;
    struct mkd_ {
	ref key, dict;
    } aelt;
    if (r_has_type(pattr, t_null)) {
	check_op(4);
	make_null(op - 3);
	make_true(op - 2);
	pop(2);
	return 0;
    }
    check_type(*preq, t_dictionary);
    check_dict_read(*preq);
    check_type(*pattr, t_dictionary);
    check_dict_read(*pattr);
    check_type(*ppol, t_dictionary);
    check_dict_read(*ppol);
    check_array(*pkeys);
    check_read(*pkeys);
    switch (code = dict_int_null_param(preq, "MediaPosition", 0, 0x7fff,
				       0, &mepos)) {
	default:
	    return code;
	case 2:
	case 1:
	    mepos = -1;
	case 0:;
    }
    switch (code = dict_int_null_param(preq, "Orientation", 0, 3,
				       0, &orient)) {
	default:
	    return code;
	case 2:
	case 1:
	    orient = -1;
	case 0:;
    }
    code = dict_bool_param(preq, "RollFedMedia", false, &roll);
    if (code < 0)
	return code;
    code = dict_int_param(ppol, "PolicyNotFound", 0, 7, 0,
			  &policy_default);
    if (code < 0)
	return code;
    if (dict_find_string(pattr, "Priority", &ppriority) > 0) {
	check_array_only(*ppriority);
	check_read(*ppriority);
    } else {
	make_empty_array(&no_priority, a_readonly);
	ppriority = &no_priority;
    }
    match.no_match_priority = r_size(ppriority);
    reset_match(&match);
    for (ai = dict_first(pattr);
	 (ai = dict_next(pattr, ai, (ref * /*[2]*/)&aelt)) >= 0;
	 ) {
	if (r_has_type(&aelt.dict, t_dictionary) &&
	    r_has_attr(dict_access_ref(&aelt.dict), a_read) &&
	    r_has_type(&aelt.key, t_integer)
	    ) {
	    bool match_all;
	    uint ki, pi;

	    code = dict_bool_param(&aelt.dict, "MatchAll", false,
				   &match_all);
	    if (code < 0)
		return code;
	    for (ki = 0; ki < r_size(pkeys); ki++) {
		ref key;
		ref kstr;
		ref *prvalue;
		ref *pmvalue;
		ref *ppvalue;
		int policy;

		array_get(imemory, pkeys, ki, &key);
		if (dict_find(&aelt.dict, &key, &pmvalue) <= 0)
		    continue;
		if (dict_find(preq, &key, &prvalue) <= 0 ||
		    r_has_type(prvalue, t_null)
		    ) {
		    if (match_all)
			goto no;
		    else
			continue;
		}
		/* Look for the Policies entry for this key. */
		if (dict_find(ppol, &key, &ppvalue) > 0) {
		    check_type_only(*ppvalue, t_integer);
		    policy = ppvalue->value.intval;
		} else
		    policy = policy_default;
	/*
	 * Match a requested attribute value with the attribute value in the
	 * description of a medium.  For all attributes except PageSize,
	 * matching means equality.  PageSize is special; see match_page_size
	 * below.
	 */
		if (r_has_type(&key, t_name) &&
		    (name_string_ref(imemory, &key, &kstr),
		     r_size(&kstr) == 8 &&
		     !memcmp(kstr.value.bytes, "PageSize", 8))
		    ) {
		    gs_matrix ignore_mat;
		    gs_point ignore_msize;

		    if (zmatch_page_size(imemory, prvalue, pmvalue,
					 policy, orient, roll,
					 &best_mismatch,
					 &ignore_mat,
					 &ignore_msize)
			<= 0)
			goto no;
		} else if (!obj_eq(imemory, prvalue, pmvalue))
		    goto no;
	    }

	    mepos_penalty = (mepos < 0 || aelt.key.value.intval == mepos) ?
		0 : .001;

	    /* We have a match. Save the match in case no better match is found */
	    if (r_has_type(&match.match_key, t_null)) 
		match.match_key = aelt.key;
	    /*
	     * If it is a better match than the current best it supersedes it 
	     * regardless of priority. If the match is the same, then update 
	     * to the current only if the key value is lower.
	     */
	    if (best_mismatch + mepos_penalty <= mbest) {
		if (best_mismatch + mepos_penalty < mbest  ||
		    (r_has_type(&match.match_key, t_integer) &&
		     match.match_key.value.intval > aelt.key.value.intval)) {
		    reset_match(&match);
		    match.match_key = aelt.key;
		    mbest = best_mismatch + mepos_penalty;
		}
	    }
	    /* In case of a tie, see if the new match has priority. */
	    for (pi = match.priority; pi > 0;) {
		ref pri;

		pi--;
		array_get(imemory, ppriority, pi, &pri);
		if (obj_eq(imemory, &aelt.key, &pri)) {	/* Yes, higher priority. */
		    match.best_key = aelt.key;
		    match.priority = pi;
		    break;
		}
	    }
no:;
	}
    }
    if (r_has_type(&match.match_key, t_null)) {
	make_false(op - 3);
	pop(3);
    } else {
	if (r_has_type(&match.best_key, t_null))
	    op[-3] = match.match_key;
	else
	    op[-3] = match.best_key;
	make_true(op - 2);
	pop(2);
    }
    return 0;
}
Ejemplo n.º 5
0
int
zdefault_make_font(gs_font_dir * pdir, const gs_font * oldfont,
                   const gs_matrix * pmat, gs_font ** ppfont)
{
    gs_font *newfont = *ppfont;
    gs_memory_t *mem = newfont->memory;
    /* HACK: we know this font was allocated by the interpreter. */
    gs_ref_memory_t *imem = (gs_ref_memory_t *)mem;
    ref *fp = pfont_dict(oldfont);
    font_data *pdata;
    ref newdict, newmat, scalemat;
    uint dlen = dict_maxlength(fp);
    uint mlen = dict_length(fp) + 3;	/* FontID, OrigFont, ScaleMatrix */
    int code;

    if (dlen < mlen)
        dlen = mlen;
    if ((pdata = gs_alloc_struct(mem, font_data, &st_font_data,
                                 "make_font(font_data)")) == 0
        )
        return_error(e_VMerror);
    /*
     * This dictionary is newly created: it's safe to pass NULL as the
     * dstack pointer to dict_copy and dict_put_string.
     */
    if ((code = dict_alloc(imem, dlen, &newdict)) < 0 ||
        (code = dict_copy(fp, &newdict, NULL)) < 0 ||
        (code = gs_alloc_ref_array(imem, &newmat, a_all, 12,
                                   "make_font(matrices)")) < 0
        )
        return code;
    refset_null_new(newmat.value.refs, 12, imemory_new_mask(imem));
    ref_assign(&scalemat, &newmat);
    r_set_size(&scalemat, 6);
    scalemat.value.refs += 6;
    /*
     * Create the scaling matrix.  We could do this several different
     * ways: by "dividing" the new FontMatrix by the base FontMatrix, by
     * multiplying the current scaling matrix by a ScaleMatrix kept in
     * the gs_font, or by multiplying the current scaling matrix by the
     * ScaleMatrix from the font dictionary.  We opt for the last of
     * these.
     */
    {
        gs_matrix scale, prev_scale;
        ref *ppsm;

        if (!(dict_find_string(fp, "ScaleMatrix", &ppsm) > 0 &&
              read_matrix(mem, ppsm, &prev_scale) >= 0 &&
              gs_matrix_multiply(pmat, &prev_scale, &scale) >= 0)
            )
            scale = *pmat;
        write_matrix_new(&scalemat, &scale, imem);
    }
    r_clear_attrs(&scalemat, a_write);
    r_set_size(&newmat, 6);
    write_matrix_new(&newmat, &newfont->FontMatrix, imem);
    r_clear_attrs(&newmat, a_write);
    if ((code = dict_put_string(&newdict, "FontMatrix", &newmat, NULL)) < 0 ||
        (code = dict_put_string(&newdict, "OrigFont", pfont_dict(oldfont->base), NULL)) < 0 ||
        (code = dict_put_string(&newdict, "ScaleMatrix", &scalemat, NULL)) < 0 ||
        (code = add_FID(NULL, &newdict, newfont, imem)) < 0
        )
        return code;
    newfont->client_data = pdata;
    *pdata = *pfont_data(oldfont);
    pdata->dict = newdict;
    r_clear_attrs(dict_access_ref(&newdict), a_write);
    return 0;
}
Ejemplo n.º 6
0
/* or a negative error code. */
int
build_gs_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font ** ppfont, font_type ftype,
              gs_memory_type_ptr_t pstype, const build_proc_refs * pbuild,
              build_font_options_t options)
{
    ref kname;			/* t_string */
    ref *pftype;
    ref *pencoding = 0;
    bool bitmapwidths;
    int exactsize, inbetweensize, transformedchar;
    int wmode;
    int code;
    gs_font *pfont;
    ref *pfid;
    ref *aop = dict_access_ref(op);
    bool cpsi_mode = gs_currentcpsimode(imemory);

    get_font_name(imemory, &kname, op - 1);
    if (dict_find_string(op, "FontType", &pftype) <= 0 ||
        !r_has_type(pftype, t_integer) ||
        pftype->value.intval != (int)ftype
        )
        return_error(e_invalidfont);
    if (dict_find_string(op, "Encoding", &pencoding) <= 0) {
        if (!(options & bf_Encoding_optional))
            return_error(e_invalidfont);
        pencoding = 0;
    } else {
        if (!r_is_array(pencoding))
            return_error(e_invalidfont);
    }
    if (pencoding) {   /* observed Adobe behavior */
        int count = r_size(pencoding);
        int type = ftype ? t_name : t_integer;
        bool fixit = false;

        while (count--) {
           ref r;
           if ((code = array_get(imemory, pencoding, count, &r)) < 0 ||
             !(r_has_type(&r, type) || r_has_type(&r, t_null))) {
               if (!cpsi_mode && ftype == ft_user_defined) {
                   if (code < 0 || r_has_type(&r, t_null)) {
                       return_error(e_typecheck);
                   }
                   fixit = true;
                   break;
               }
               else {
                   return_error(e_typecheck);
               }
           }
        }

        /* For at least Type 3 fonts, Adobe Distiller will "fix" an Encoding array, as in, for example
         * Bug 692681 where the arrays contain integers rather than names. Once the font is instantiated
         * the integers have been converted to names.
         * It is preferable to to this manipulation here, rather than in Postscript, because we are less
         * restricted by read-only attributes and VM save levels.
         */
        if (fixit) {
            ref penc;
            uint size = 0;
            char buf[32], *bptr;
            avm_space curglob = ialloc_space(idmemory);
            avm_space useglob = r_is_local(pencoding) ? avm_local : avm_global;

            ialloc_set_space(idmemory, useglob);
            
            count = r_size(pencoding);
            if ((code = ialloc_ref_array(&penc, (r_type_attrs(pencoding) & a_readonly), count, "build_gs_font")) < 0)
                 return code;
            
            while (count--) {
               ref r;
               if (array_get(imemory, pencoding, count, &r) < 0){
                   return_error(e_typecheck);
               }
               /* For type 3, we know the Encoding entries must be names */
               if (r_has_type(&r, t_name)){
                   ref_assign(&(penc.value.refs[count]), &r);
               }
               else {
               
                   if ((code = obj_cvs(imemory, &r, (byte *)buf, 32, &size, (const byte **)(&bptr))) < 0) {
                       return(code);
                   }
                   if ((code = name_ref(imemory, (const byte *)bptr, size, &r, true)) < 0)
                        return code;
                   ref_assign(&(penc.value.refs[count]), &r);
               }
            }
            
            if ((code = dict_put_string(osp, "Encoding", &penc, NULL)) < 0)
               return code;
            ialloc_set_space(idmemory, curglob);
        }
    }
    if ((code = dict_int_param(op, "WMode", 0, 1, 0, &wmode)) < 0 ||
        (code = dict_bool_param(op, "BitmapWidths", false, &bitmapwidths)) < 0 ||
        (code = dict_int_param(op, "ExactSize", 0, 2, fbit_use_bitmaps, &exactsize)) < 0 ||
        (code = dict_int_param(op, "InBetweenSize", 0, 2, fbit_use_outlines, &inbetweensize)) < 0 ||
        (code = dict_int_param(op, "TransformedChar", 0, 2, fbit_use_outlines, &transformedchar)) < 0
        )
        return code;
    code = dict_find_string(op, "FID", &pfid);
    if (code > 0 && r_has_type(pfid, t_fontID)) { /* silently ignore invalid FID per CET 13-05.ps */
        /*
         * If this font has a FID entry already, it might be a scaled font
         * made by makefont or scalefont; in a Level 2 environment, it might
         * be an existing font being registered under a second name, or a
         * re-encoded font (which was invalid in Level 1, but dvips did it
         * anyway).
         */
        pfont = r_ptr(pfid, gs_font);
        /*
         * If the following condition is false this is a re-encoded font,
         * or some other questionable situation in which the FID
         * was preserved.  Pretend the FID wasn't there.
         */
        if (obj_eq(pfont->memory, pfont_dict(pfont), op)) {
            if (pfont->base == pfont) {	/* original font */
                if (!level2_enabled)
                    return_error(e_invalidfont);
                *ppfont = pfont;
                return 1;
            } else {		/* This was made by makefont or scalefont. */
                /* Just insert the new name. */
                gs_matrix mat;
                ref fname;			/* t_string */

                code = sub_font_params(imemory, op, &mat, NULL, &fname);
                if (code < 0)
                    return code;
                code = 1;
                copy_font_name(&pfont->font_name, &fname);
                goto set_name;
            }
        }
    }
    /* This is a new font. */
    if (!r_has_attr(aop, a_write))
        return_error(e_invalidaccess);
    {
        ref encoding;

        /*
         * Since add_FID may resize the dictionary and cause
         * pencoding to become invalid, save the Encoding.
         */
        if (pencoding) {
            encoding = *pencoding;
            pencoding = &encoding;
        }
        code = build_gs_sub_font(i_ctx_p, op, &pfont, ftype, pstype,
                                 pbuild, pencoding, op);
        if (code < 0)
            return code;
    }
    pfont->BitmapWidths = bitmapwidths;
    pfont->ExactSize = (fbit_type)exactsize;
    pfont->InBetweenSize = (fbit_type)inbetweensize;
    pfont->TransformedChar = (fbit_type)transformedchar;
    pfont->WMode = wmode;
    pfont->procs.font_info = zfont_info;
    code = 0;
set_name:
    copy_font_name(&pfont->key_name, &kname);
    *ppfont = pfont;
    return code;
}