From 5123260e329a44db83edf4b1378cb7101632f7eb Mon Sep 17 00:00:00 2001 From: Ray Johnston Date: Sat, 20 Jun 2020 19:08:20 -0700 Subject: Fix Bug 701852. Problems with the plane_extract device. First, the plane_begin_typed_image function used the gs_gstate_copy_temp, but since this was allocated as a st_gs_gstate, and the reference counts were not handled (as the comment describes), freeing that object would decrement the ref_counts, causing premature free of objects. Remove this dangerous function. Change to use gs_gstate_copy so we have a proper gs_gstate structure. Using gs_gstate_copy from a clist playback gstate requires that we have client colors and device colors in the color[0] and color[1] elements. Allocate, and initialize these, then free upon exit from clist_playback. Also, the mem device underlying the plane_extract device needs to be retained so that it is not prematurely freed. --- base/gdevplnx.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'base/gdevplnx.c') diff --git a/base/gdevplnx.c b/base/gdevplnx.c index 37ed6414c..3a85b6d03 100644 --- a/base/gdevplnx.c +++ b/base/gdevplnx.c @@ -29,6 +29,7 @@ #include "gxgetbit.h" #include "gxiparam.h" #include "gxgstate.h" +#include "gsstate.h" #include "gdevplnx.h" /* Define the size of the locally allocated bitmap buffers. */ @@ -428,6 +429,7 @@ plane_device_init(gx_device_plane_extract *edev, gx_device *target, gx_device_set_target((gx_device_forward *)edev, target); gx_device_copy_params((gx_device *)edev, target); edev->plane_dev = plane_dev; + gx_device_retain(plane_dev, true); edev->plane = *render_plane; plane_open_device((gx_device *)edev); if (clear) { @@ -841,6 +843,8 @@ typedef struct plane_image_enum_s { const gs_gstate *pgs; /* original gs_gstate */ gs_gstate *pgs_image; /* modified gs_gstate state */ } plane_image_enum_t; +/* Note that we include the pgs_image which is 'bytes' type (not gs_gstate) */ +/* It still needs to be traced so that a GC won't free it prematurely. */ gs_private_st_suffix_add3(st_plane_image_enum, plane_image_enum_t, "plane_image_enum_t", plane_image_enum_enum_ptrs, plane_image_enum_reloc_ptrs, st_gx_image_enum_common, info, pgs, pgs_image); @@ -991,10 +995,9 @@ plane_begin_typed_image(gx_device * dev, } info = gs_alloc_struct(memory, plane_image_enum_t, &st_plane_image_enum, "plane_image_begin_typed(info)"); - pgs_image = gs_gstate_copy_temp(pgs, memory); + pgs_image = gs_gstate_copy(pgs, memory); if (pgs_image == 0 || info == 0) goto fail; - *pgs_image = *pgs; pgs_image->client_data = info; pgs_image->get_cmap_procs = plane_get_cmap_procs; code = dev_proc(edev->plane_dev, begin_typed_image) @@ -1034,6 +1037,7 @@ plane_image_end_image(gx_image_enum_common_t * info, bool draw_last) plane_image_enum_t * const ppie = (plane_image_enum_t *)info; int code = gx_image_end(ppie->info, draw_last); + ppie->pgs_image->client_data = NULL; /* this isn't a complete client_data struct */ gs_free_object(ppie->memory, ppie->pgs_image, "plane_image_end_image(pgs_image)"); gx_image_free_enum(&info); -- cgit v1.2.1