summaryrefslogtreecommitdiff
path: root/psi
diff options
context:
space:
mode:
authorChris Liddell <chris.liddell@artifex.com>2022-06-28 13:23:02 +0100
committerChris Liddell <chris.liddell@artifex.com>2022-06-30 08:38:45 +0100
commitb609c25f7f881bea4b10c8e1b9b950b635437320 (patch)
tree509268d9364b536b3d567006397bce30945c07cd /psi
parent6f4326ab21ae055610c72222da4ab2ac26007589 (diff)
downloadghostpdl-b609c25f7f881bea4b10c8e1b9b950b635437320.tar.gz
oss-fuzz 48305: Use ref counting for subclass child device
The .currentoutputdevice (custom) operator leaves the chance that PS VM still has a reference to the "child" of a subclassed device. In normal operation, this isn't a problem, but on an error, that PS reference may persist until after the unsubclass operation, meaning the "child" is freed while there is still an active reference to it. Change the code to use reference counting to ensure that works. This means considerable fiddling to ensure that, after subclassing, anything sent to the (now moribund) child device doesn't end up affecting the parent.
Diffstat (limited to 'psi')
-rw-r--r--psi/zdevice.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/psi/zdevice.c b/psi/zdevice.c
index 99beaff7f..7e9779f7e 100644
--- a/psi/zdevice.c
+++ b/psi/zdevice.c
@@ -45,7 +45,7 @@ ENUM_PTRS_WITH(psi_device_ref_enum_ptrs, psi_device_ref *devref)
}
case 0:
{
- if (devref->device->memory != NULL) {
+ if (devref->device != NULL && devref->device->memory != NULL) {
ENUM_RETURN(gx_device_enum_ptr(devref->device));
}
return 0;
@@ -54,7 +54,7 @@ ENUM_PTRS_END
static
RELOC_PTRS_WITH(psi_device_ref_reloc_ptrs, psi_device_ref *devref)
- if (devref->device->memory != NULL) {
+ if (devref->device != NULL && devref->device->memory != NULL) {
devref->device = gx_device_reloc_ptr(devref->device, gcst);
}
RELOC_PTRS_END
@@ -71,7 +71,7 @@ psi_device_ref_finalize(const gs_memory_t *cmem, void *vptr)
/* pdref->device->memory == NULL indicates either a device prototype
or a device allocated on the stack rather than the heap
*/
- if (pdref->device->memory != NULL)
+ if (pdref->device != NULL && pdref->device->memory != NULL)
rc_decrement(pdref->device, "psi_device_ref_finalize");
pdref->device = NULL;
@@ -456,6 +456,7 @@ zmakewordimagedevice(i_ctx_t *i_ctx_p)
return_error(gs_error_VMerror);
}
psdev->device = new_dev;
+ rc_increment(new_dev);
make_tav(op - 4, t_device, imemory_space(iimemory) | a_all, pdevice, psdev);
pop(4);
}