summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Sharp <ken.sharp@artifex.com>2018-10-25 14:30:08 +0100
committerKen Sharp <ken.sharp@artifex.com>2018-10-25 14:30:08 +0100
commit04333a6f1344df6b5069880cafe7b190d0984601 (patch)
tree36b6295bff2a5f5fbf386001714143573badbd53
parentffac21a73b74c8ce01cbae406f7dd3bfd0a7ef65 (diff)
downloadghostpdl-04333a6f1344df6b5069880cafe7b190d0984601.tar.gz
Fix pngalpha device with device subclassing
Bug #699815 "Segmentation fault for pdf input to pngalpha driver" The pngalpha device, in pngalpha_create_buf_device() first creates an in-memory rendering device (image32) and then overrides two of the device methods with its own versions. This doesn't work at all when we have subclassing devices loaded, because the device that gets handed as the 'target' device is the head of the chain of devices, and the pngalpha device simply pulls the methods directly from that device. Note that this also wouldn't work if a forwarding device were present. We can work around it by descending the chain of devices, and pulling the methods from the last device in the chain instead of using the 'target' directly. This still feels wrong but it should at least work.
-rw-r--r--devices/gdevpng.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/devices/gdevpng.c b/devices/gdevpng.c
index 26fc5a8ab..b41162be3 100644
--- a/devices/gdevpng.c
+++ b/devices/gdevpng.c
@@ -765,10 +765,28 @@ pngalpha_create_buf_device(gx_device **pbdev, gx_device *target, int y,
const gx_render_plane_t *render_plane, gs_memory_t *mem,
gx_color_usage_t *color_usage)
{
- gx_device_printer *ptarget = (gx_device_printer *)target;
+ gx_device_printer *ptarget;
int code = gx_default_create_buf_device(pbdev, target, y,
render_plane, mem, color_usage);
/* Now set copy_alpha to one that handles RGBA */
+
+ /* this is really pretty nasty. The pngalpha device is going to replace
+ * the device methods in the memory rendering device with some of its own.
+ * To me this seems fraught with peril, its making a lot of assumptions
+ * about the compatibility of the devices!
+ * This, of course, totally breaks device chaining, but since the memory
+ * device wasn't going to pass on the intermediate method calls to the
+ * 'terminating' device, we can work around it here. We simply descend
+ * the chain of devices to the terminating device, and pull the methods
+ * we need directly from that device. I don't know why we are using
+ * 'orig_procs' either, but its safe to do so because this is only
+ * done here for the PNG device, and we know that this is a gx_device_prn
+ * based device.
+ */
+ while (target->child != NULL)
+ target = target->child;
+
+ ptarget= (gx_device_printer *)target;
set_dev_proc(*pbdev, copy_alpha, ptarget->orig_procs.copy_alpha);
set_dev_proc(*pbdev, fillpage, pngalpha_fillpage);
return code;