From d49dbf133ac49d09d626bab08ee92835a50a646a Mon Sep 17 00:00:00 2001
From: ray <Ray.Johnston@artifex.com>
Date: Tue, 24 Mar 2020 16:49:13 -0700
Subject: [PATCH] Fix bug 702182: VMerror due to leaks in pattern cache due to
 locking.

If the tile being loaded by the clist reader was already in the cache and
was locked, the slot would be re-loaded (with the same tile) without freeing
up the previously loaded tile. It would be nicer to be able to skip reading
the tile in this case, but we need to consume the data from the clist sequence,
so just unlock it so it can be freed, then re-load it (presumably setting the
lock again).
---
 base/gsptype1.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/base/gsptype1.c b/base/gsptype1.c
index 7d4714f..c39f039 100644
--- a/base/gsptype1.c
+++ b/base/gsptype1.c
@@ -2117,8 +2117,20 @@ gx_dc_pattern_read(
             /* the following works for raster or clist patterns */
             cache_space_needed = buf.size_b + buf.size_c;
         }
+
+        /* Free up any unlocked patterns if needed */
         gx_pattern_cache_ensure_space((gs_gstate *)pgs, cache_space_needed);
 
+        /* If the pattern tile is already in the cache, make sure it isn't locked */
+        /* The lock will be reset below, but the read logic needs to finish loading the pattern. */
+        ptile = &(pgs->pattern_cache->tiles[buf.id % pgs->pattern_cache->num_tiles]);
+        if (ptile->id != gs_no_id && ptile->is_locked) {
+            /* we shouldn't have miltiple tiles locked, but check if OK before unlocking */
+            if (ptile->id != buf.id)
+                return_error(gs_error_unregistered);	/* can't unlock some other tile in this slot */
+            code = gx_pattern_cache_entry_set_lock(pgs, buf.id, false);        /* make sure not locked */
+        }
+        /* get_entry will free the tile in the cache slot if it isn't empty */
         code = gx_pattern_cache_get_entry((gs_gstate *)pgs, /* Break 'const'. */
                         buf.id, &ptile);
         if (code < 0)
-- 
1.8.3.1

