summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Liddell <chris.liddell@artifex.com>2021-06-18 12:00:17 +0100
committerChris Liddell <chris.liddell@artifex.com>2021-06-18 13:25:06 +0100
commite9ac9ec0bfa060aecc23440451c75c859c62206a (patch)
tree7d15cf71c9822e29b526a181f69c2a26f906c9f1
parent2b9fab55953ae02f94ed15b2939c1f4a59dce8be (diff)
downloadghostpdl-e9ac9ec0bfa060aecc23440451c75c859c62206a.tar.gz
Pattern instance life span problem with pdfi in gsgpdf_gs_text_filter_032
When pdfi is called from gs (i.e. using the gs graphics state), the pattern tile cache exists outside, and lasts beyond the "life", of the pdfi instance. But pattern instances do not. That causes a crash when Ghostscript runs the end of job restore, and the garbager tries to access the pattern instance, via the clist accumulator device in the pattern tile cache. So, have pdfi remove tile cache entries for relevant patterns when the pattern instances get freed.
-rw-r--r--pdf/pdf_pattern.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/pdf/pdf_pattern.c b/pdf/pdf_pattern.c
index a66b6ba52..c0432343c 100644
--- a/pdf/pdf_pattern.c
+++ b/pdf/pdf_pattern.c
@@ -111,13 +111,32 @@ static void pdfi_free_pattern_context(pdf_pattern_context_t *context)
gs_free_object(context->ctx->memory, context, "Free pattern context");
}
+static bool
+pdfi_pattern_purge_proc(gx_color_tile * ctile, void *proc_data)
+{
+ gs_id id = (gs_id)proc_data;
+ if (ctile->id == id)
+ return true;
+ return false;
+}
+
void pdfi_pattern_cleanup(gs_memory_t * mem, void *p)
{
gs_pattern1_instance_t *pinst = (gs_pattern1_instance_t *)p;
pdf_pattern_context_t *context;
+ gx_color_tile *pctile = NULL;
context = (pdf_pattern_context_t *)pinst->client_data;
+ /* If are being called from Ghostscript, the clist pattern accumulator device (in
+ the tile cache) *can* outlast outlast our pattern instance, so if the pattern
+ instance is being freed, also remove the entry from the cache
+ */
+ if (gx_pattern_cache_get_entry(context->ctx->pgs, pinst->id, &pctile) == 0
+ && gx_pattern_tile_is_clist(pctile)) {
+ gx_pattern_cache_winnow(gstate_pattern_cache(context->ctx->pgs), pdfi_pattern_purge_proc, (void *)(pctile->id));
+ }
+
if (context != NULL) {
pdfi_free_pattern_context(context);
pinst->client_data = NULL;