diff options
-rw-r--r-- | Resource/Init/gs_setpd.ps | 20 | ||||
-rw-r--r-- | psi/zdevice2.c | 55 |
2 files changed, 56 insertions, 19 deletions
diff --git a/Resource/Init/gs_setpd.ps b/Resource/Init/gs_setpd.ps index b75c4312a..8fa7c51df 100644 --- a/Resource/Init/gs_setpd.ps +++ b/Resource/Init/gs_setpd.ps | |||
@@ -96,7 +96,7 @@ level2dict begin | |||
96 | % we must (carefully) reinstall the old parameters in | 96 | % we must (carefully) reinstall the old parameters in |
97 | % the same device. | 97 | % the same device. |
98 | .currentpagedevice pop //null currentdevice //null | 98 | .currentpagedevice pop //null currentdevice //null |
99 | {.trysetparams} .internalstopped | 99 | { .trysetparams } .internalstopped |
100 | { | 100 | { |
101 | //null | 101 | //null |
102 | } if | 102 | } if |
@@ -104,26 +104,32 @@ level2dict begin | |||
104 | { pop pop } | 104 | { pop pop } |
105 | { | 105 | { |
106 | SETPDDEBUG { (Error in .trysetparams!) = pstack flush } if | 106 | SETPDDEBUG { (Error in .trysetparams!) = pstack flush } if |
107 | cleartomark pop pop pop | 107 | {cleartomark pop pop pop} .internalstopped pop |
108 | % if resetting the entire device state failed, at least put back the | 108 | % if resetting the entire device state failed, at least put back the |
109 | % security related key | 109 | % security related key |
110 | currentdevice //null //false mark /.LockSafetyParams .currentpagedevice pop | 110 | currentdevice //null //false mark /.LockSafetyParams |
111 | /.LockSafetyParams .knownget not {//false} if .putdeviceparamsonly | 111 | currentpagedevice /.LockSafetyParams .knownget not |
112 | {systemdict /SAFER .knownget not {//false} } if | ||
113 | .putdeviceparamsonly | ||
112 | /.installpagedevice cvx /rangecheck signalerror | 114 | /.installpagedevice cvx /rangecheck signalerror |
113 | } | 115 | } |
114 | ifelse pop pop | 116 | ifelse pop pop |
115 | % A careful reading of the Red Book reveals that an erasepage | 117 | % A careful reading of the Red Book reveals that an erasepage |
116 | % should occur, but *not* an initgraphics. | 118 | % should occur, but *not* an initgraphics. |
117 | erasepage .beginpage | 119 | erasepage .beginpage |
118 | } bind def | 120 | } bind executeonly def |
119 | 121 | ||
120 | /.uninstallpagedevice | 122 | /.uninstallpagedevice |
121 | { 2 .endpage { .currentnumcopies //false .outputpage } if | 123 | { |
124 | {2 .endpage { .currentnumcopies //false .outputpage } if} .internalstopped pop | ||
122 | nulldevice | 125 | nulldevice |
123 | } bind def | 126 | } bind def |
124 | 127 | ||
125 | (%grestorepagedevice) cvn | 128 | (%grestorepagedevice) cvn |
126 | { .uninstallpagedevice grestore .installpagedevice | 129 | { |
130 | .uninstallpagedevice | ||
131 | grestore | ||
132 | .installpagedevice | ||
127 | } bind def | 133 | } bind def |
128 | 134 | ||
129 | (%grestoreallpagedevice) cvn | 135 | (%grestoreallpagedevice) cvn |
diff --git a/psi/zdevice2.c b/psi/zdevice2.c index 0c7080d57..5447c8c84 100644 --- a/psi/zdevice2.c +++ b/psi/zdevice2.c | |||
@@ -251,8 +251,8 @@ z2currentgstate(i_ctx_t *i_ctx_p) | |||
251 | /* ------ Wrappers for operators that reset the graphics state. ------ */ | 251 | /* ------ Wrappers for operators that reset the graphics state. ------ */ |
252 | 252 | ||
253 | /* Check whether we need to call out to restore the page device. */ | 253 | /* Check whether we need to call out to restore the page device. */ |
254 | static bool | 254 | static int |
255 | restore_page_device(const gs_gstate * pgs_old, const gs_gstate * pgs_new) | 255 | restore_page_device(i_ctx_t *i_ctx_p, const gs_gstate * pgs_old, const gs_gstate * pgs_new) |
256 | { | 256 | { |
257 | gx_device *dev_old = gs_currentdevice(pgs_old); | 257 | gx_device *dev_old = gs_currentdevice(pgs_old); |
258 | gx_device *dev_new; | 258 | gx_device *dev_new; |
@@ -260,9 +260,10 @@ restore_page_device(const gs_gstate * pgs_old, const gs_gstate * pgs_new) | |||
260 | gx_device *dev_t2; | 260 | gx_device *dev_t2; |
261 | bool samepagedevice = obj_eq(dev_old->memory, &gs_int_gstate(pgs_old)->pagedevice, | 261 | bool samepagedevice = obj_eq(dev_old->memory, &gs_int_gstate(pgs_old)->pagedevice, |
262 | &gs_int_gstate(pgs_new)->pagedevice); | 262 | &gs_int_gstate(pgs_new)->pagedevice); |
263 | bool LockSafetyParams = dev_old->LockSafetyParams; | ||
263 | 264 | ||
264 | if ((dev_t1 = (*dev_proc(dev_old, get_page_device)) (dev_old)) == 0) | 265 | if ((dev_t1 = (*dev_proc(dev_old, get_page_device)) (dev_old)) == 0) |
265 | return false; | 266 | return 0; |
266 | /* If we are going to putdeviceparams in a callout, we need to */ | 267 | /* If we are going to putdeviceparams in a callout, we need to */ |
267 | /* unlock temporarily. The device will be re-locked as needed */ | 268 | /* unlock temporarily. The device will be re-locked as needed */ |
268 | /* by putdeviceparams from the pgs_old->pagedevice dict state. */ | 269 | /* by putdeviceparams from the pgs_old->pagedevice dict state. */ |
@@ -271,23 +272,44 @@ restore_page_device(const gs_gstate * pgs_old, const gs_gstate * pgs_new) | |||
271 | dev_new = gs_currentdevice(pgs_new); | 272 | dev_new = gs_currentdevice(pgs_new); |
272 | if (dev_old != dev_new) { | 273 | if (dev_old != dev_new) { |
273 | if ((dev_t2 = (*dev_proc(dev_new, get_page_device)) (dev_new)) == 0) | 274 | if ((dev_t2 = (*dev_proc(dev_new, get_page_device)) (dev_new)) == 0) |
274 | return false; | 275 | samepagedevice = true; |
275 | if (dev_t1 != dev_t2) | 276 | else if (dev_t1 != dev_t2) |
276 | return true; | 277 | samepagedevice = false; |
278 | } | ||
279 | |||
280 | if (LockSafetyParams && !samepagedevice) { | ||
281 | os_ptr op = osp; | ||
282 | const int max_ops = 512; | ||
283 | |||
284 | /* The %grestorepagedevice must complete: the biggest danger | ||
285 | is operand stack overflow. As we use get/putdeviceparams | ||
286 | that means pushing all the device params onto the stack, | ||
287 | pdfwrite having by far the largest number of parameters | ||
288 | at (currently) 212 key/value pairs - thus needing (currently) | ||
289 | 424 entries on the op stack. Allowing for working stack | ||
290 | space, and safety margin..... | ||
291 | */ | ||
292 | if (max_ops > op - osbot) { | ||
293 | if (max_ops >= ref_stack_count(&o_stack)) | ||
294 | return_error(gs_error_stackoverflow); | ||
295 | } | ||
277 | } | 296 | } |
278 | /* | 297 | /* |
279 | * The current implementation of setpagedevice just sets new | 298 | * The current implementation of setpagedevice just sets new |
280 | * parameters in the same device object, so we have to check | 299 | * parameters in the same device object, so we have to check |
281 | * whether the page device dictionaries are the same. | 300 | * whether the page device dictionaries are the same. |
282 | */ | 301 | */ |
283 | return !samepagedevice; | 302 | return samepagedevice ? 0 : 1; |
284 | } | 303 | } |
285 | 304 | ||
286 | /* - grestore - */ | 305 | /* - grestore - */ |
287 | static int | 306 | static int |
288 | z2grestore(i_ctx_t *i_ctx_p) | 307 | z2grestore(i_ctx_t *i_ctx_p) |
289 | { | 308 | { |
290 | if (!restore_page_device(igs, gs_gstate_saved(igs))) | 309 | int code = restore_page_device(i_ctx_p, igs, gs_gstate_saved(igs)); |
310 | if (code < 0) return code; | ||
311 | |||
312 | if (code == 0) | ||
291 | return gs_grestore(igs); | 313 | return gs_grestore(igs); |
292 | return push_callout(i_ctx_p, "%grestorepagedevice"); | 314 | return push_callout(i_ctx_p, "%grestorepagedevice"); |
293 | } | 315 | } |
@@ -297,7 +319,9 @@ static int | |||
297 | z2grestoreall(i_ctx_t *i_ctx_p) | 319 | z2grestoreall(i_ctx_t *i_ctx_p) |
298 | { | 320 | { |
299 | for (;;) { | 321 | for (;;) { |
300 | if (!restore_page_device(igs, gs_gstate_saved(igs))) { | 322 | int code = restore_page_device(i_ctx_p, igs, gs_gstate_saved(igs)); |
323 | if (code < 0) return code; | ||
324 | if (code == 0) { | ||
301 | bool done = !gs_gstate_saved(gs_gstate_saved(igs)); | 325 | bool done = !gs_gstate_saved(gs_gstate_saved(igs)); |
302 | 326 | ||
303 | gs_grestore(igs); | 327 | gs_grestore(igs); |
@@ -328,11 +352,15 @@ z2restore(i_ctx_t *i_ctx_p) | |||
328 | if (code < 0) return code; | 352 | if (code < 0) return code; |
329 | 353 | ||
330 | while (gs_gstate_saved(gs_gstate_saved(igs))) { | 354 | while (gs_gstate_saved(gs_gstate_saved(igs))) { |
331 | if (restore_page_device(igs, gs_gstate_saved(igs))) | 355 | code = restore_page_device(i_ctx_p, igs, gs_gstate_saved(igs)); |
356 | if (code < 0) return code; | ||
357 | if (code > 0) | ||
332 | return push_callout(i_ctx_p, "%restore1pagedevice"); | 358 | return push_callout(i_ctx_p, "%restore1pagedevice"); |
333 | gs_grestore(igs); | 359 | gs_grestore(igs); |
334 | } | 360 | } |
335 | if (restore_page_device(igs, gs_gstate_saved(igs))) | 361 | code = restore_page_device(i_ctx_p, igs, gs_gstate_saved(igs)); |
362 | if (code < 0) return code; | ||
363 | if (code > 0) | ||
336 | return push_callout(i_ctx_p, "%restorepagedevice"); | 364 | return push_callout(i_ctx_p, "%restorepagedevice"); |
337 | 365 | ||
338 | code = dorestore(i_ctx_p, asave); | 366 | code = dorestore(i_ctx_p, asave); |
@@ -355,9 +383,12 @@ static int | |||
355 | z2setgstate(i_ctx_t *i_ctx_p) | 383 | z2setgstate(i_ctx_t *i_ctx_p) |
356 | { | 384 | { |
357 | os_ptr op = osp; | 385 | os_ptr op = osp; |
386 | int code; | ||
358 | 387 | ||
359 | check_stype(*op, st_igstate_obj); | 388 | check_stype(*op, st_igstate_obj); |
360 | if (!restore_page_device(igs, igstate_ptr(op))) | 389 | code = restore_page_device(i_ctx_p, igs, igstate_ptr(op)); |
390 | if (code < 0) return code; | ||
391 | if (code == 0) | ||
361 | return zsetgstate(i_ctx_p); | 392 | return zsetgstate(i_ctx_p); |
362 | return push_callout(i_ctx_p, "%setgstatepagedevice"); | 393 | return push_callout(i_ctx_p, "%setgstatepagedevice"); |
363 | } | 394 | } |