summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Sharp <ken.sharp@artifex.com>2018-09-20 10:09:37 +0100
committerKen Sharp <ken.sharp@artifex.com>2018-09-20 10:21:49 +0100
commit90e8f8d32b64bae015e19e85e693988daaea54f4 (patch)
tree28df369829943fdb308eb33a9018c82ec133dcbf
parentc1657e3b874261e254d4e132499355b22f3dd46a (diff)
downloadghostpdl-90e8f8d32b64bae015e19e85e693988daaea54f4.tar.gz
Bug #699796 "copydevice fails after stack device copies invalidated"
This isn't anything to do with .fill_identity_cmap. A simpler example is: .distillerdevice nulldevice copydevice The problem is that when we execute nulldevice we need to invalidate any copies, stored on the operand stack, of the device that was current before the nulldevice was installed. We do that by setting the pdevice member of the device structure to NULL. However the fact that a device can be invalidated has clearly passed by a number of developers in the intervening years, and a number of places in the code do check the type of the operand is a device, but they don't check to see if the device has been invalidated. Add validation checks where required.
-rw-r--r--psi/idisp.c4
-rw-r--r--psi/zdevice.c18
2 files changed, 22 insertions, 0 deletions
diff --git a/psi/idisp.c b/psi/idisp.c
index 2ca7b57c5..c65671c74 100644
--- a/psi/idisp.c
+++ b/psi/idisp.c
@@ -81,6 +81,10 @@ display_set_callback(gs_main_instance *minst, display_callback *callback)
* setting callback, then reopen it.
*/
check_read_type(op[-1], t_device);
+ if (op[-1].value.pdevice == NULL)
+ /* This can happen if we invalidated devices on the stack by calling nulldevice after they were pushed */
+ return_error(gs_error_undefined);
+
dev = op[-1].value.pdevice;
was_open = dev->is_open;
diff --git a/psi/zdevice.c b/psi/zdevice.c
index 7d5f58df9..6d2ce0511 100644
--- a/psi/zdevice.c
+++ b/psi/zdevice.c
@@ -46,6 +46,10 @@ zcopydevice2(i_ctx_t *i_ctx_p)
check_read_type(op[-1], t_device);
check_type(*op, t_boolean);
+ if (op[-1].value.pdevice == NULL)
+ /* This can happen if we invalidated devices on the stack by calling nulldevice after they were pushed */
+ return_error(gs_error_undefined);
+
code = gs_copydevice2(&new_dev, op[-1].value.pdevice, op->value.boolval,
imemory);
if (code < 0)
@@ -108,6 +112,10 @@ zdevicename(i_ctx_t *i_ctx_p)
const char *dname;
check_read_type(*op, t_device);
+ if (op->value.pdevice == NULL)
+ /* This can happen if we invalidated devices on the stack by calling nulldevice after they were pushed */
+ return_error(gs_error_undefined);
+
dname = op->value.pdevice->dname;
make_const_string(op, avm_foreign | a_readonly, strlen(dname),
(const byte *)dname);
@@ -157,6 +165,10 @@ zgetbitsrect(i_ctx_t *i_ctx_p)
check_read_type(op[-7], t_device);
dev = op[-7].value.pdevice;
+ if (dev == NULL)
+ /* This can happen if we invalidated devices on the stack by calling nulldevice after they were pushed */
+ return_error(gs_error_undefined);
+
check_int_leu(op[-6], dev->width);
rect.p.x = op[-6].value.intval;
check_int_leu(op[-5], dev->height);
@@ -274,6 +286,9 @@ zget_device_params(i_ctx_t *i_ctx_p, bool is_hardware)
}
rkeys = *op;
dev = op[-1].value.pdevice;
+ if (op[-1].value.pdevice == NULL)
+ /* This can happen if we invalidated devices on the stack by calling nulldevice after they were pushed */
+ return_error(gs_error_undefined);
pop(1);
stack_param_list_write(&list, &o_stack, &rkeys, iimemory);
code = gs_get_device_or_hardware_params(dev, (gs_param_list *) & list,
@@ -440,6 +455,9 @@ zputdeviceparams(i_ctx_t *i_ctx_p)
check_type_only(*prequire_all, t_boolean);
check_write_type_only(*pdev, t_device);
dev = pdev->value.pdevice;
+ if (dev == NULL)
+ /* This can happen if we invalidated devices on the stack by calling nulldevice after they were pushed */
+ return_error(gs_error_undefined);
code = stack_param_list_read(&list, &o_stack, 0, ppolicy,
prequire_all->value.boolval, iimemory);
if (code < 0)