summaryrefslogtreecommitdiff
path: root/base/gdevsclass.c
diff options
context:
space:
mode:
authorKen Sharp <ken.sharp@artifex.com>2021-03-01 11:17:29 +0000
committerKen Sharp <ken.sharp@artifex.com>2021-03-01 15:01:33 +0000
commit1001daa79a087fc6dcc8ceb5078d241db0a7c4c7 (patch)
tree3642b4e5f9c7de927de83baf54bbc97c4420a8be /base/gdevsclass.c
parentc41f3a797b1809639c6db4d4990bcf81a155f4d3 (diff)
downloadghostpdl-1001daa79a087fc6dcc8ceb5078d241db0a7c4c7.tar.gz
Fix seg faults in subclassing
Commit a754bd375a625368567947b1e1b77ce3e5c06a3f fixed a different class of seg faults, but unfortunately removed a crucial line of code. When the child device has pushed a compositor, we still need to check to see if the compositor is pointing at the child device. If it is not then the compositor must have pushed more than a single device, so it is not safe to behave as if the target of the compositor is our child device. Originally I had hoped to walk down the forwarding devices until we reach our device, but the actual behaviour of the pdf14 device in combination with the clist, when the final device is ps2write renders that all but impossible, as well as unnecessary. In this case the compositor action starts by defining a new device, It then pushes a pdf14_accum device (there are 3, one per device space) it then pushes the pdf14clist device in front of that. Finally it turns the device it first created into a forwarding device, and points its target at the original device. So we return with 3 new devices pushed, not just one. However, the final forwarding device is in fact forwarding to the subclassing device and the device reference counting magic is applied to the forwarding device, which means we don't need to dance around with the references to the subclassing device and child. We could detect this condition by checking the name of the target device of the pdf14clist forwarding device, but that isn't really any better than simply assuming that the compositor takes care of inserting new devices correctly. The pdf14_accum devices are not forwarding devices, they store the pdf14 device in a member called saved_pdev14, so we can't readily follow that either. Finally there is no way to determine if a device is a forwarding device, or a gx_device_pdf14_accum type which limits the amount of checking we cna perform. This is an interim commit to work around the problem, because we are about to do a release. A better fix which eliminates all (we hope) of the hidden assumptions and magic knowledge in the code here will be committed shortly, but may be too risky for the release.
Diffstat (limited to 'base/gdevsclass.c')
-rw-r--r--base/gdevsclass.c24
1 files changed, 13 insertions, 11 deletions
diff --git a/base/gdevsclass.c b/base/gdevsclass.c
index b9cc089ac..f5430e292 100644
--- a/base/gdevsclass.c
+++ b/base/gdevsclass.c
@@ -502,21 +502,23 @@ int default_subclass_create_compositor(gx_device *dev, gx_device **pcdev, const
*/
gx_device_forward *fdev = (gx_device_forward *)*pcdev;
- if (gs_is_pdf14trans_compositor(pcte) != 0 && strncmp(fdev->dname, "pdf14clist", 10) == 0) {
- pdf14_clist_device *p14dev;
+ if(fdev->target == dev->child) {
+ if (gs_is_pdf14trans_compositor(pcte) != 0 && strncmp(fdev->dname, "pdf14clist", 10) == 0) {
+ pdf14_clist_device *p14dev;
- p14dev = (pdf14_clist_device *)*pcdev;
+ p14dev = (pdf14_clist_device *)*pcdev;
- dev->color_info = dev->child->color_info;
+ dev->color_info = dev->child->color_info;
- psubclass_data->saved_compositor_method = p14dev->procs.create_compositor;
- psubclass_data->forwarding_dev = fdev;
- p14dev->procs.create_compositor = gx_subclass_create_compositor;
- }
+ psubclass_data->saved_compositor_method = p14dev->procs.create_compositor;
+ psubclass_data->forwarding_dev = fdev;
+ p14dev->procs.create_compositor = gx_subclass_create_compositor;
+ }
- fdev->target = dev;
- rc_decrement_only(dev->child, "subclass compositor code");
- rc_increment(dev);
+ fdev->target = dev;
+ rc_decrement_only(dev->child, "subclass compositor code");
+ rc_increment(dev);
+ }
/* Return 1 so that *pcdev becomes the current device. */
return 1;
}