From 6a3c36f8c5e83448f5d1e5f24ee01c0e80a92877 Mon Sep 17 00:00:00 2001
From: Ray Johnston <ray.johnston@artifex.com>
Date: Fri, 27 Mar 2020 13:54:02 -0700
Subject: [PATCH] Fix Bug 702177: VMerrors with some BufferSpace and/or -K
 limits.

Interestingly, the two examples given in the bug succeed on Windows 64
but don't on linux. The difference is due to an 8 byte difference in the
size of gx_clist_state (the per band writer state). In the case of the
Bug690546.pdf file, the space left in the BufferSpace area after the
logic increased it was only 2,200 bytes on linux, but was 12k bytes on
Windows (it made an extra pass through the automatic "increase space"
loop in gdev_prn_setup_as_command_list. Fix the calculation in
clist_init_states so that the amount of extra space corresponds to the
amount expected by clist command writing (data_bits_size + cmd_largest_size)
rather than the insufficient and arbitrary "100".

Note that although the Bug692057.pdf returned VMerror from cmd_put_list_op, the
'fallback; method of gx_default_strip_tile_rectangle still produces the SAME
raster from psdcmyk16 and does not change the performance or clist file size
Robin's commit cbee0840 fixed this case.
---
 base/gxclist.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/base/gxclist.c b/base/gxclist.c
index 1819e58..667d9c0 100644
--- a/base/gxclist.c
+++ b/base/gxclist.c
@@ -355,12 +355,13 @@ clist_init_states(gx_device * dev, byte * init_data, uint data_size)
     /* Align to the natural boundary for ARM processors, bug 689600 */
     long alignment = (-(long)init_data) & (sizeof(init_data) - 1);
 
-    /*
-     * The +100 in the next line is bogus, but we don't know what the
-     * real check should be. We're effectively assuring that at least 100
-     * bytes will be available to buffer command operands.
+    /* Leave enough room after states for commands that write a reasonable
+     * amount of data. The cmd_largest_size and the data_bits_size should  be
+     * enough to buffer command operands. The data_bits_size is the level
+     * at which commands should expect to split data across buffers. If this
+     * extra space is a little large, it doesn't really hurt.
      */
-    if (state_size + sizeof(cmd_prefix) + cmd_largest_size + 100 + alignment > data_size)
+    if (state_size + sizeof(cmd_prefix) + cmd_largest_size + data_bits_size + alignment > data_size)
         return_error(gs_error_rangecheck);
     /* The end buffer position is not affected by alignment */
     cdev->cend = init_data + data_size;
-- 
1.8.3.1

