Exemple #1
0
/*
 * If the new save level is zero, fix up the contents of a stack
 * by clearing the l_new bit in all the entries (since we can't tolerate
 * values with l_new set if the save level is zero).
 * Also, in any case, fix up the e-stack by replacing empty executable
 * strings and closed executable files that are newer than the save
 * with canonical ones that aren't.
 *
 * Note that this procedure is only called if restore_check_stack succeeded.
 */
static void
restore_fix_stack(ref_stack_t * pstack, const alloc_save_t * asave,
                  bool is_estack)
{
    ref_stack_enum_t rsenum;

    ref_stack_enum_begin(&rsenum, pstack);
    do {
        ref *stkp = rsenum.ptr;
        uint size = rsenum.size;

        for (; size; stkp++, size--) {
            r_clear_attrs(stkp, l_new);		/* always do it, no harm */
            if (is_estack) {
                ref ofile;

                ref_assign(&ofile, stkp);
                switch (r_type(stkp)) {
                case t_string:
                    if (r_size(stkp) == 0 &&
                            alloc_is_since_save(stkp->value.bytes,
                                                asave)
                       ) {
                        make_empty_const_string(stkp,
                                                avm_foreign);
                        break;
                    }
                    continue;
                case t_file:
                    if (alloc_is_since_save(stkp->value.pfile,
                                            asave)
                       ) {
                        make_invalid_file(stkp);
                        break;
                    }
                    continue;
                default:
                    continue;
                }
                r_copy_attrs(stkp, a_all | a_executable,
                             &ofile);
            }
        }
    } while (ref_stack_enum_next(&rsenum));
}
/* Remove entries from font and character caches. */
int
font_restore(const alloc_save_t * save)
{

    gs_memory_t *smem = gs_save_any_memory(save);
    gs_font_dir *pdir = smem->gs_lib_ctx->font_dir;
    const gs_memory_t *mem = 0;
    int code;

    if (pdir == 0)		/* not initialized yet */
        return 0;

    /* Purge original (unscaled) fonts. */

    {
        gs_font *pfont;

otop:
        for (pfont = pdir->orig_fonts; pfont != 0;
             pfont = pfont->next
            ) {
            mem = pfont->memory;
            if (alloc_is_since_save((char *)pfont, save)) {
                code = gs_purge_font(pfont);
                if (code < 0)
                    return code;
                goto otop;
            }
        }
    }

    /* Purge cached scaled fonts. */

    {
        gs_font *pfont;

top:
        for (pfont = pdir->scaled_fonts; pfont != 0;
             pfont = pfont->next
            ) {
            if (alloc_is_since_save((char *)pfont, save)) {
                code = gs_purge_font(pfont);
                if (code < 0)
                    return code;
                goto top;
            }
        }
    }

    /* Purge xfonts and uncached scaled fonts. */

    {
        cached_fm_pair *pair;
        uint n;

        for (pair = pdir->fmcache.mdata, n = pdir->fmcache.mmax;
             n > 0; pair++, n--
            )
            if (!fm_pair_is_free(pair)) {
#if 0
                /* We disabled this code portion because
                   gx_add_fm_pair now copied xvalues
                   into a stable memory.
                 */
                if ((uid_is_XUID(&pair->UID) &&
                     alloc_is_since_save((char *)pair->UID.xvalues,
                                         save))
                    ) {
                    code = gs_purge_fm_pair(pdir, pair, 0);
                    if (code < 0)
                        return code;
                    continue;
                }
#endif
                if (pair->font != 0 &&
                    alloc_is_since_save((char *)pair->font, save)
                    ) {
                    if (!uid_is_valid(&pair->UID))
                        gs_clean_fm_pair(pdir, pair);
                    /* Don't discard pairs with a surviving UID. */
                    pair->font = 0;
                }
                if (pair->xfont != 0 &&
                    alloc_is_since_save((char *)pair->xfont, save)
                    ) {
                    code = gs_purge_fm_pair(pdir, pair, 1);
                    if (code < 0)
                        return code;
                }
            }
    }

    /* Purge characters with names about to be removed. */
    /* We only need to do this if any new names have been created */
    /* since the save. */

    if (alloc_any_names_since_save(save))
        gx_purge_selected_cached_chars(pdir, purge_if_name_removed,
                                       (void *)save);
    return 0;
}
Exemple #3
0
/* Check a stack to make sure all its elements are older than a save. */
static int
restore_check_stack(const i_ctx_t *i_ctx_p, const ref_stack_t * pstack,
                    const alloc_save_t * asave, bool is_estack)
{
    ref_stack_enum_t rsenum;

    ref_stack_enum_begin(&rsenum, pstack);
    do {
        const ref *stkp = rsenum.ptr;
        uint size = rsenum.size;

        for (; size; stkp++, size--) {
            const void *ptr;

            switch (r_type(stkp)) {
            case t_array:
                /*
                 * Zero-length arrays are a special case: see the
                 * t_*array case (label rr:) in igc.c:gc_trace.
                 */
                if (r_size(stkp) == 0) {
                    /*stkp->value.refs = (void *)0;*/
                    continue;
                }
                ptr = stkp->value.refs;
                break;
            case t_dictionary:
                ptr = stkp->value.pdict;
                break;
            case t_file:
                /* Don't check executable or closed literal */
                /* files on the e-stack. */
            {
                stream *s;

                if (is_estack &&
                        (r_has_attr(stkp, a_executable) ||
                         file_is_invalid(s, stkp))
                   )
                    continue;
            }
            ptr = stkp->value.pfile;
            break;
            case t_name:
                /* Names are special because of how they are allocated. */
                if (alloc_name_is_since_save((const gs_memory_t *)pstack->memory,
                                             stkp, asave))
                    return_error(e_invalidrestore);
                continue;
            case t_string:
                /* Don't check empty executable strings */
                /* on the e-stack. */
                if (r_size(stkp) == 0 &&
                        r_has_attr(stkp, a_executable) && is_estack
                   )
                    continue;
                ptr = stkp->value.bytes;
                break;
            case t_mixedarray:
            case t_shortarray:
                /* See the t_array case above. */
                if (r_size(stkp) == 0) {
                    /*stkp->value.packed = (void *)0;*/
                    continue;
                }
                ptr = stkp->value.packed;
                break;
            case t_device:
                ptr = stkp->value.pdevice;
                break;
            case t_fontID:
            case t_struct:
            case t_astruct:
                ptr = stkp->value.pstruct;
                break;
            case t_save:
                /* See the comment in isave.h regarding the following. */
                if (i_ctx_p->language_level <= 2)
                    continue;
                ptr = alloc_find_save(&gs_imemory, stkp->value.saveid);
                /*
                 * Invalid save objects aren't supposed to be possible
                 * in LL3, but just in case....
                 */
                if (ptr == 0)
                    return_error(e_invalidrestore);
                if (ptr == asave)
                    continue;
                break;
            default:
                continue;
            }
            if (alloc_is_since_save(ptr, asave))
                return_error(e_invalidrestore);
        }
    } while (ref_stack_enum_next(&rsenum));
    return 0;		/* OK */
}