diff options
author | Ken Sharp <ken.sharp@artifex.com> | 2018-10-25 14:30:08 +0100 |
---|---|---|
committer | Ken Sharp <ken.sharp@artifex.com> | 2018-10-25 14:30:08 +0100 |
commit | 04333a6f1344df6b5069880cafe7b190d0984601 (patch) | |
tree | 36b6295bff2a5f5fbf386001714143573badbd53 | |
parent | ffac21a73b74c8ce01cbae406f7dd3bfd0a7ef65 (diff) | |
download | ghostpdl-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.c | 20 |
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; |