summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Liddell <chris.liddell@artifex.com>2018-08-23 14:13:25 +0100
committerChris Liddell <chris.liddell@artifex.com>2018-08-23 15:41:05 +0100
commitc432131c3fdb2143e148e8ba88555f7f7a63b25e (patch)
treebe33325404f1d31a0a5a2e5483bab17450fc4dfb
parent0b6cd1918e1ec4ffd087400a754a845180a4522b (diff)
Bug 699661: Avoid sharing pointers between pdf14 compositors
If a copdevice is triggered when the pdf14 compositor is the device, we make a copy of the device, then throw an error because, by default we're only allowed to copy the device prototype - then freeing it calls the finalize, which frees several pointers shared with the parent. Make a pdf14 specific finish_copydevice() which NULLs the relevant pointers, before, possibly, throwing the same error as the default method. This also highlighted a problem with reopening the X11 devices, where a custom error handler could be replaced with itself, meaning it also called itself, and infifite recursion resulted. Keep a note of if the handler replacement has been done, and don't do it a second time.
-rw-r--r--base/gdevp14.c17
-rw-r--r--devices/gdevxini.c12
2 files changed, 24 insertions, 5 deletions
diff --git a/base/gdevp14.c b/base/gdevp14.c
index d9f8e794c..eb9cc23bc 100644
--- a/base/gdevp14.c
+++ b/base/gdevp14.c
@@ -178,6 +178,7 @@ static dev_proc_fill_mask(pdf14_fill_mask);
178static dev_proc_stroke_path(pdf14_stroke_path); 178static dev_proc_stroke_path(pdf14_stroke_path);
179static dev_proc_begin_typed_image(pdf14_begin_typed_image); 179static dev_proc_begin_typed_image(pdf14_begin_typed_image);
180static dev_proc_text_begin(pdf14_text_begin); 180static dev_proc_text_begin(pdf14_text_begin);
181static dev_proc_finish_copydevice(pdf14_finish_copydevice);
181static dev_proc_create_compositor(pdf14_create_compositor); 182static dev_proc_create_compositor(pdf14_create_compositor);
182static dev_proc_create_compositor(pdf14_forward_create_compositor); 183static dev_proc_create_compositor(pdf14_forward_create_compositor);
183static dev_proc_begin_transparency_group(pdf14_begin_transparency_group); 184static dev_proc_begin_transparency_group(pdf14_begin_transparency_group);
@@ -245,7 +246,7 @@ static const gx_color_map_procs *
245 pdf14_create_compositor, /* create_compositor */\ 246 pdf14_create_compositor, /* create_compositor */\
246 NULL, /* get_hardware_params */\ 247 NULL, /* get_hardware_params */\
247 pdf14_text_begin, /* text_begin */\ 248 pdf14_text_begin, /* text_begin */\
248 NULL, /* finish_copydevice */\ 249 pdf14_finish_copydevice, /* finish_copydevice */\
249 pdf14_begin_transparency_group,\ 250 pdf14_begin_transparency_group,\
250 pdf14_end_transparency_group,\ 251 pdf14_end_transparency_group,\
251 pdf14_begin_transparency_mask,\ 252 pdf14_begin_transparency_mask,\
@@ -3935,6 +3936,19 @@ pdf14_text_begin(gx_device * dev, gs_gstate * pgs,
3935 return code; 3936 return code;
3936} 3937}
3937 3938
3939static int
3940pdf14_finish_copydevice(gx_device *new_dev, const gx_device *from_dev)
3941{
3942 pdf14_device *pdev = (pdf14_device*)new_dev;
3943
3944 pdev->ctx = NULL;
3945 pdev->trans_group_parent_cmap_procs = NULL;
3946 pdev->smaskcolor = NULL;
3947
3948 /* Only allow copying the prototype. */
3949 return (from_dev->memory ? gs_note_error(gs_error_rangecheck) : 0);
3950}
3951
3938/* 3952/*
3939 * Implement copy_mono by filling lots of small rectangles. 3953 * Implement copy_mono by filling lots of small rectangles.
3940 */ 3954 */
@@ -8093,6 +8107,7 @@ c_pdf14trans_clist_read_update(gs_composite_t * pcte, gx_device * cdev,
8093 before reopening the device */ 8107 before reopening the device */
8094 if (p14dev->ctx != NULL) { 8108 if (p14dev->ctx != NULL) {
8095 pdf14_ctx_free(p14dev->ctx); 8109 pdf14_ctx_free(p14dev->ctx);
8110 p14dev->ctx = NULL;
8096 } 8111 }
8097 dev_proc(tdev, open_device) (tdev); 8112 dev_proc(tdev, open_device) (tdev);
8098 } 8113 }
diff --git a/devices/gdevxini.c b/devices/gdevxini.c
index 8511eac80..23b8c35a6 100644
--- a/devices/gdevxini.c
+++ b/devices/gdevxini.c
@@ -59,7 +59,8 @@ static struct xv_ {
59 Boolean alloc_error; 59 Boolean alloc_error;
60 XErrorHandler orighandler; 60 XErrorHandler orighandler;
61 XErrorHandler oldhandler; 61 XErrorHandler oldhandler;
62} x_error_handler; 62 Boolean set;
63} x_error_handler = {0};
63 64
64static int 65static int
65x_catch_alloc(Display * dpy, XErrorEvent * err) 66x_catch_alloc(Display * dpy, XErrorEvent * err)
@@ -74,7 +75,8 @@ x_catch_alloc(Display * dpy, XErrorEvent * err)
74int 75int
75x_catch_free_colors(Display * dpy, XErrorEvent * err) 76x_catch_free_colors(Display * dpy, XErrorEvent * err)
76{ 77{
77 if (err->request_code == X_FreeColors) 78 if (err->request_code == X_FreeColors ||
79 x_error_handler.orighandler == x_catch_free_colors)
78 return 0; 80 return 0;
79 return x_error_handler.orighandler(dpy, err); 81 return x_error_handler.orighandler(dpy, err);
80} 82}
@@ -274,8 +276,10 @@ gdev_x_open(gx_device_X * xdev)
274 return_error(gs_error_ioerror); 276 return_error(gs_error_ioerror);
275 } 277 }
276 /* Buggy X servers may cause a Bad Access on XFreeColors. */ 278 /* Buggy X servers may cause a Bad Access on XFreeColors. */
277 x_error_handler.orighandler = XSetErrorHandler(x_catch_free_colors); 279 if (!x_error_handler.set) {
278 280 x_error_handler.orighandler = XSetErrorHandler(x_catch_free_colors);
281 x_error_handler.set = True;
282 }
279 /* Get X Resources. Use the toolkit for this. */ 283 /* Get X Resources. Use the toolkit for this. */
280 XtToolkitInitialize(); 284 XtToolkitInitialize();
281 app_con = XtCreateApplicationContext(); 285 app_con = XtCreateApplicationContext();