summaryrefslogtreecommitdiff
path: root/base/gdevepo.c
diff options
context:
space:
mode:
authorChris Liddell <chris.liddell@artifex.com>2018-08-28 07:52:18 +0100
committerChris Liddell <chris.liddell@artifex.com>2018-08-28 08:05:15 +0100
commitc9b362ba908ca4b1d7c72663a33229588012d7d9 (patch)
treeab159641333f52838a38aff8ca6540b1ba38923c /base/gdevepo.c
parentea735ba37dc0fd5f5622d031830b9a559dec1cc9 (diff)
downloadghostpdl-c9b362ba908ca4b1d7c72663a33229588012d7d9.tar.gz
Bug 699670: disallow copying of the epo device
The erasepage optimisation (epo) subclass device shouldn't be allowed to be copied because the subclass private data, child and parent pointers end up being shared between the original device and the copy. Add an epo_finish_copydevice which NULLs the three offending pointers, and then communicates to the caller that copying is not allowed. This also exposed a separate issue with the stype for subclasses devices. Devices are, I think, unique in having two stype objects associated with them: the usual one in the memory manager header, and the other stored in the device structere directly. In order for the stype to be correct, we have to use the stype for the incoming device, with the ssize of the original device (ssize should reflect the size of the memory allocation). We correctly did so with the stype in the device structure, but then used the prototype device's stype to patch the memory manager stype - meaning the ssize potentially no longer matched the allocated memory. This caused problems in the garbager where there is an implicit assumption that the size of a single object clump (c_alone == 1) is also the size (+ memory manager overheads) of the single object it contains. The solution is to use the same stype instance to patch the memory manager data as we do in the device structure (with the correct ssize).
Diffstat (limited to 'base/gdevepo.c')
-rw-r--r--base/gdevepo.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/base/gdevepo.c b/base/gdevepo.c
index e3abb6b72..77ab4f698 100644
--- a/base/gdevepo.c
+++ b/base/gdevepo.c
@@ -64,6 +64,7 @@ static dev_proc_put_image(epo_put_image);
static dev_proc_fillpage(epo_fillpage);
static dev_proc_create_compositor(epo_create_compositor);
static dev_proc_text_begin(epo_text_begin);
+static dev_proc_finish_copydevice(epo_finish_copydevice);
static dev_proc_begin_image(epo_begin_image);
static dev_proc_begin_typed_image(epo_begin_typed_image);
static dev_proc_stroke_path(epo_stroke_path);
@@ -152,7 +153,7 @@ gx_device_epo gs_epo_device =
epo_create_compositor,
default_subclass_get_hardware_params, /* get_hardware_params */
epo_text_begin,
- default_subclass_finish_copydevice, /* finish_copydevice */
+ epo_finish_copydevice, /* finish_copydevice */
default_subclass_begin_transparency_group, /* begin_transparency_group */
default_subclass_end_transparency_group, /* end_transparency_group */
default_subclass_begin_transparency_mask, /* begin_transparency_mask */
@@ -497,6 +498,20 @@ int epo_text_begin(gx_device *dev, gs_gstate *pgs, const gs_text_params_t *text,
return dev_proc(dev, text_begin)(dev, pgs, text, font, path, pdcolor, pcpath, memory, ppte);
}
+int epo_finish_copydevice(gx_device *dev, const gx_device *from_dev)
+{
+ /* We musn't allow the following pointers to remain shared with the from_dev
+ because we're about to tell the caller it's only allowed to copy the prototype
+ and free the attempted copy of a non-prototype. If from_dev is the prototype
+ these pointers won't be set, anyway.
+ */
+ dev->child = NULL;
+ dev->parent = NULL;
+ dev->subclass_data = NULL;
+ /* Only allow copying the prototype. */
+ return (from_dev->memory ? gs_note_error(gs_error_rangecheck) : 0);
+}
+
int epo_begin_image(gx_device *dev, const gs_gstate *pgs, const gs_image_t *pim,
gs_image_format_t format, const gs_int_rect *prect,
const gx_drawing_color *pdcolor, const gx_clip_path *pcpath,