From: Chris Liddell Date: Thu, 23 Aug 2018 13:13:25 +0000 (+0100) Subject: Bug 699661: Avoid sharing pointers between pdf14 compositors 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. https://git.ghostscript.com/?p=ghostpdl.git;a=commit;h=c432131c3fdb2143e148e8ba88555f7f7a63b25e --- diff -up ghostscript-9.07/base/gdevp14.c.cve-2018-16540 ghostscript-9.07/base/gdevp14.c --- ghostscript-9.07/base/gdevp14.c.cve-2018-16540 2019-01-14 12:57:56.324331784 +0100 +++ ghostscript-9.07/base/gdevp14.c 2019-01-14 13:00:38.224433442 +0100 @@ -176,6 +176,7 @@ static dev_proc_fill_mask(pdf14_fill_mas static dev_proc_stroke_path(pdf14_stroke_path); static dev_proc_begin_typed_image(pdf14_begin_typed_image); static dev_proc_text_begin(pdf14_text_begin); +static dev_proc_finish_copydevice(pdf14_finish_copydevice); static dev_proc_create_compositor(pdf14_create_compositor); static dev_proc_create_compositor(pdf14_forward_create_compositor); static dev_proc_begin_transparency_group(pdf14_begin_transparency_group); @@ -246,7 +247,7 @@ static const gx_color_map_procs * pdf14_create_compositor, /* create_compositor */\ NULL, /* get_hardware_params */\ pdf14_text_begin, /* text_begin */\ - NULL, /* finish_copydevice */\ + pdf14_finish_copydevice, /* finish_copydevice */\ pdf14_begin_transparency_group,\ pdf14_end_transparency_group,\ pdf14_begin_transparency_mask,\ @@ -3217,6 +3218,19 @@ pdf14_text_begin(gx_device * dev, gs_ima return code; } +static int +pdf14_finish_copydevice(gx_device *new_dev, const gx_device *from_dev) +{ + pdf14_device *pdev = (pdf14_device*)new_dev; + + pdev->ctx = NULL; + pdev->trans_group_parent_cmap_procs = NULL; + pdev->smaskcolor = NULL; + + /* Only allow copying the prototype. */ + return (from_dev->memory ? gs_note_error(gs_error_rangecheck) : 0); +} + /* * Implement copy_mono by filling lots of small rectangles. */ @@ -7499,6 +7513,7 @@ c_pdf14trans_clist_read_update(gs_compos before reopening the device */ if (p14dev->ctx != NULL) { pdf14_ctx_free(p14dev->ctx); + p14dev->ctx = NULL; } dev_proc(tdev, open_device) (tdev); } diff -up ghostscript-9.07/base/gdevxini.c.cve-2018-16540 ghostscript-9.07/base/gdevxini.c --- ghostscript-9.07/base/gdevxini.c.cve-2018-16540 2019-01-14 13:01:43.310670279 +0100 +++ ghostscript-9.07/base/gdevxini.c 2019-01-14 13:04:10.937939293 +0100 @@ -59,7 +59,8 @@ static struct xv_ { Boolean alloc_error; XErrorHandler orighandler; XErrorHandler oldhandler; -} x_error_handler; + Boolean set; +} x_error_handler = {0}; static int x_catch_alloc(Display * dpy, XErrorEvent * err) @@ -74,7 +75,8 @@ x_catch_alloc(Display * dpy, XErrorEvent int x_catch_free_colors(Display * dpy, XErrorEvent * err) { - if (err->request_code == X_FreeColors) + if (err->request_code == X_FreeColors || + x_error_handler.orighandler == x_catch_free_colors) return 0; return x_error_handler.orighandler(dpy, err); } @@ -274,8 +276,10 @@ gdev_x_open(gx_device_X * xdev) return_error(gs_error_ioerror); } /* Buggy X servers may cause a Bad Access on XFreeColors. */ - x_error_handler.orighandler = XSetErrorHandler(x_catch_free_colors); - + if (!x_error_handler.set) { + x_error_handler.orighandler = XSetErrorHandler(x_catch_free_colors); + x_error_handler.set = True; + } /* Get X Resources. Use the toolkit for this. */ XtToolkitInitialize(); app_con = XtCreateApplicationContext();