diff --git a/sys/lib/ghostscript/gs_init.ps b/sys/lib/ghostscript/gs_init.ps index 17a5f69b3..31e7ec84b 100644 --- a/sys/lib/ghostscript/gs_init.ps +++ b/sys/lib/ghostscript/gs_init.ps @@ -1992,6 +1992,17 @@ readonly def % If we are running in SAFER mode, lock things down SAFER { .setsafe } if +/UndefinePostScriptOperators { + [ + /condition /currentcontext /detach /.fork /join /.localfork /lock /monitor /notify + /wait /yield /.currentscreenphase /.setscreenphase /.image2 /eoviewclip /initviewclip + /viewclip /viewclippath /defineusername + /currentalpha /setalpha /.alphaimage /composite /compositerect /dissolve /sizeimagebox /.sizeimageparams + ] + {systemdict exch .forceundef} forall + //systemdict /UndefinePostScriptOperators .forceundef +} bind def + % If we delayed binding, make it possible to do it later. /.bindnow { currentuserparams /IdiomRecognition .knownget { @@ -2005,6 +2016,7 @@ SAFER { .setsafe } if //systemdict /.delaybind {} .forceput % reclaim the space //systemdict /.bindnow .forceundef % ditto put + //systemdict /UndefinePostScriptOperators get exec //systemdict /.forcedef .forceundef % remove temptation //systemdict /.forceput .forceundef % ditto //systemdict /.forceundef .forceundef % ditto diff --git a/sys/src/cmd/gs/lib/gs_init.ps b/sys/src/cmd/gs/lib/gs_init.ps index 17a5f69b3..31e7ec84b 100644 --- a/sys/src/cmd/gs/lib/gs_init.ps +++ b/sys/src/cmd/gs/lib/gs_init.ps @@ -1992,6 +1992,17 @@ readonly def % If we are running in SAFER mode, lock things down SAFER { .setsafe } if +/UndefinePostScriptOperators { + [ + /condition /currentcontext /detach /.fork /join /.localfork /lock /monitor /notify + /wait /yield /.currentscreenphase /.setscreenphase /.image2 /eoviewclip /initviewclip + /viewclip /viewclippath /defineusername + /currentalpha /setalpha /.alphaimage /composite /compositerect /dissolve /sizeimagebox /.sizeimageparams + ] + {systemdict exch .forceundef} forall + //systemdict /UndefinePostScriptOperators .forceundef +} bind def + % If we delayed binding, make it possible to do it later. /.bindnow { currentuserparams /IdiomRecognition .knownget { @@ -2005,6 +2016,7 @@ SAFER { .setsafe } if //systemdict /.delaybind {} .forceput % reclaim the space //systemdict /.bindnow .forceundef % ditto put + //systemdict /UndefinePostScriptOperators get exec //systemdict /.forcedef .forceundef % remove temptation //systemdict /.forceput .forceundef % ditto //systemdict /.forceundef .forceundef % ditto diff --git a/sys/src/cmd/gs/src/gsdevice.c b/sys/src/cmd/gs/src/gsdevice.c index 8a4dbc259..45d19562e 100644 --- a/sys/src/cmd/gs/src/gsdevice.c +++ b/sys/src/cmd/gs/src/gsdevice.c @@ -480,21 +480,30 @@ gx_device_retain(gx_device *dev, bool retained) int gs_nulldevice(gs_state * pgs) { - if (pgs->device == 0 || !gx_device_is_null(pgs->device)) { - gx_device *ndev; - int code = gs_copydevice(&ndev, (const gx_device *)&gs_null_device, - pgs->memory); + int code = 0; + int saveLockSafety = false; + if (pgs->device == 0 || !gx_device_is_null(pgs->device)) { + gx_device *ndev; + code = gs_copydevice(&ndev, (const gx_device *)&gs_null_device, pgs->memory); if (code < 0) return code; + if (gs_currentdevice_inline(pgs) != NULL) + saveLockSafety = gs_currentdevice_inline(pgs)->LockSafetyParams; + /* * Internal devices have a reference count of 0, not 1, * aside from references from graphics states. */ rc_init(ndev, pgs->memory, 0); - return gs_setdevice_no_erase(pgs, ndev); + code = gs_setdevice_no_erase(pgs, ndev); + if (code < 0) { + gs_free_object(pgs->memory, ndev, "gs_copydevice(device)"); + return code; + } + gs_currentdevice_inline(pgs)->LockSafetyParams = saveLockSafety; } - return 0; + return code; } /* Close a device. The client is responsible for ensuring that */ diff --git a/sys/src/cmd/gs/src/isave.h b/sys/src/cmd/gs/src/isave.h index 6bceaca50..f97baf166 100644 --- a/sys/src/cmd/gs/src/isave.h +++ b/sys/src/cmd/gs/src/isave.h @@ -116,4 +116,8 @@ void alloc_set_not_in_save(gs_dual_memory_t *); /* Remove entries from font and character caches. */ void font_restore(const alloc_save_t * save); +int restore_check_save(i_ctx_t *i_ctx_p, alloc_save_t **asave); + +int dorestore(i_ctx_t *i_ctx_p, alloc_save_t *asave); + #endif /* isave_INCLUDED */ diff --git a/sys/src/cmd/gs/src/zdevice2.c b/sys/src/cmd/gs/src/zdevice2.c index f61d53d7f..7c5e02405 100644 --- a/sys/src/cmd/gs/src/zdevice2.c +++ b/sys/src/cmd/gs/src/zdevice2.c @@ -27,6 +27,7 @@ #include "igstate.h" #include "iname.h" #include "iutil.h" +#include "isave.h" #include "store.h" #include "gxdevice.h" #include "gsstate.h" @@ -312,6 +313,12 @@ z2grestoreall(i_ctx_t *i_ctx_p) private int z2restore(i_ctx_t *i_ctx_p) { + alloc_save_t *asave; + bool saveLockSafety = gs_currentdevice_inline(igs)->LockSafetyParams; + int code = restore_check_save(i_ctx_p, &asave); + + if (code < 0) return code; + while (gs_state_saved(gs_state_saved(igs))) { if (restore_page_device(igs, gs_state_saved(igs))) return push_callout(i_ctx_p, "%restore1pagedevice"); @@ -319,7 +326,10 @@ z2restore(i_ctx_t *i_ctx_p) } if (restore_page_device(igs, gs_state_saved(igs))) return push_callout(i_ctx_p, "%restorepagedevice"); - return zrestore(i_ctx_p); + code = dorestore(i_ctx_p, asave); + if (code < 0) + gs_currentdevice_inline(igs)->LockSafetyParams = saveLockSafety; + return code; } /* setgstate - */ diff --git a/sys/src/cmd/gs/src/zvmem.c b/sys/src/cmd/gs/src/zvmem.c index 3824d03f0..9def9d821 100644 --- a/sys/src/cmd/gs/src/zvmem.c +++ b/sys/src/cmd/gs/src/zvmem.c @@ -102,35 +102,52 @@ zsave(i_ctx_t *i_ctx_p) private int restore_check_operand(os_ptr, alloc_save_t **, gs_dual_memory_t *); private int restore_check_stack(const ref_stack_t *, const alloc_save_t *, bool); private void restore_fix_stack(ref_stack_t *, const alloc_save_t *, bool); + int -zrestore(i_ctx_t *i_ctx_p) +restore_check_save(i_ctx_t *i_ctx_p, alloc_save_t **asave) { os_ptr op = osp; - alloc_save_t *asave; - bool last; - vm_save_t *vmsave; - int code = restore_check_operand(op, &asave, idmemory); - + int code = restore_check_operand(op, asave, idmemory); if (code < 0) return code; if_debug2('u', "[u]vmrestore 0x%lx, id = %lu\n", - (ulong) alloc_save_client_data(asave), + (ulong) alloc_save_client_data(*asave), (ulong) op->value.saveid); if (I_VALIDATE_BEFORE_RESTORE) ivalidate_clean_spaces(i_ctx_p); /* Check the contents of the stacks. */ osp--; - { - int code; - - if ((code = restore_check_stack(&o_stack, asave, false)) < 0 || - (code = restore_check_stack(&e_stack, asave, true)) < 0 || - (code = restore_check_stack(&d_stack, asave, false)) < 0 - ) { - osp++; - return code; - } + if ((code = restore_check_stack(&o_stack, *asave, false)) < 0 || + (code = restore_check_stack(&e_stack, *asave, true)) < 0 || + (code = restore_check_stack(&d_stack, *asave, false)) < 0 + ) { + osp++; + return code; } + osp++; + return 0; +} + +/* + * the emantics of restore differ slightly between Level 1 and + * Level 2 and later - the latter inclues restoring the device + * state (whilst Level 1 didn't have "page devices" as such). + * Hence we have two restore operators - one here (Level 1) + * and one in zdevice2.c (Level 2+). For that reason, the + * operand checking and guts of the restore operation are + * separated so both implementations can use them to best + * effect. + */ +int +dorestore(i_ctx_t *i_ctx_p, alloc_save_t *asave) +{ + os_ptr op = osp; + bool last; + vm_save_t *vmsave; + int code; + + osp--; + /* Reset l_new in all stack entries if the new save level is zero. */ /* Also do some special fixing on the e-stack. */ restore_fix_stack(&o_stack, asave, false); @@ -170,9 +187,23 @@ zrestore(i_ctx_t *i_ctx_p) /* cause an 'invalidaccess' in setuserparams. Temporarily set */ /* LockFilePermissions false until the gs_lev2.ps can do a */ /* setuserparams from the restored userparam dictionary. */ + /* NOTE: This is safe to do here, since the restore has */ + /* successfully completed - this should never come before any */ + /* operation that can trigger an error */ i_ctx_p->LockFilePermissions = false; return 0; } + +int +zrestore(i_ctx_t *i_ctx_p) +{ + alloc_save_t *asave; + int code = restore_check_save(i_ctx_p, &asave); + if (code < 0) + return code; + return dorestore(i_ctx_p, asave); +} + /* Check the operand of a restore. */ private int restore_check_operand(os_ptr op, alloc_save_t ** pasave,