diff options
author | Ken Sharp <ken.sharp@artifex.com> | 2018-09-20 10:09:37 +0100 |
---|---|---|
committer | Ken Sharp <ken.sharp@artifex.com> | 2018-09-20 10:21:49 +0100 |
commit | 90e8f8d32b64bae015e19e85e693988daaea54f4 (patch) | |
tree | 28df369829943fdb308eb33a9018c82ec133dcbf | |
parent | c1657e3b874261e254d4e132499355b22f3dd46a (diff) | |
download | ghostpdl-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.c | 4 | ||||
-rw-r--r-- | psi/zdevice.c | 18 |
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) |