Blame SOURCES/ghostscript-more-than-11-elements-in-array.patch

993c09
From d2423464852664218310ae7c5610fb0b6da4218b Mon Sep 17 00:00:00 2001
993c09
From: Ken Sharp <ken.sharp@artifex.com>
993c09
Date: Fri, 7 Mar 2014 13:41:01 +0000
993c09
Subject: [PATCH] PS interpreter, vector devices and pdfwrite - remove setdash
993c09
 limit of 11
993c09
993c09
Bug #693916 "setdash does not accept more than 11 elements in the array argument"
993c09
993c09
The PostScript interpreter was already capable of this, it simply required
993c09
the limit check to be removed. The vector device needed to allocate and
993c09
free an array of floats, rather than maintain a fixed size array.
993c09
993c09
pdfwrite was teh most complex as it maintains a stack of gstates, and these
993c09
also needed to be modified to allocate and free the dash array. However the
993c09
gstate stack wasn't already a garbage collecting structure. Rather than going
993c09
to the effort of turning it into one I've opted to allocate the dash pattern
993c09
from non-gc memory.
993c09
993c09
A few PCL files show differences with pdfwrite, because previously pdfwrite
993c09
would throw an error (more than 11 elements in the dash array) and the stroked
993c09
lines would degenerate into filled rectangles, whereas now they are drawn as
993c09
stroked lines with a correct dash pattern. This is much more efficient.
993c09
993c09
The clist remains unmodified, Ray assures me that it will be handled there
993c09
without problems.
993c09
---
993c09
 Resource/Init/gs_init.ps |  1 -
993c09
 base/gdevpdf.c           |  6 ++++++
993c09
 base/gdevpdfg.c          | 32 +++++++++++++++++++++++++++-----
993c09
 base/gdevpdfx.h          |  3 ++-
993c09
 base/gdevvec.c           | 14 ++++++++++----
993c09
 base/gdevvec.h           | 13 ++++++-------
993c09
 6 files changed, 51 insertions(+), 18 deletions(-)
993c09
993c09
diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
993c09
index 0083fa3..b4a6c48 100644
993c09
--- a/Resource/Init/gs_init.ps
993c09
+++ b/Resource/Init/gs_init.ps
993c09
@@ -518,7 +518,6 @@ userdict /.echo.mode //true put
993c09
         0 .argindex type dup /integertype eq exch /realtype eq or not {
993c09
           /setdash .systemvar /typecheck signalerror
993c09
         } if
993c09
-        1 .argindex length 11 gt { /setdash .systemvar /limitcheck signalerror } if
993c09
         //setdash
993c09
 } odef
993c09
 /setdevice
993c09
diff --git a/base/gdevpdf.c b/base/gdevpdf.c
993c09
index 8416b51..d740cc1 100644
993c09
--- a/base/gdevpdf.c
993c09
+++ b/base/gdevpdf.c
993c09
@@ -2873,6 +2873,12 @@ pdf_close(gx_device * dev)
993c09
     gs_free_object(mem, pdev->Pages, "Free Pages dict");
993c09
     pdev->Pages = 0;
993c09
 
993c09
+    {
993c09
+        int i;
993c09
+        for (i=0;i < pdev->vgstack_depth;i++)
993c09
+            gs_free_object(pdev->memory->non_gc_memory, pdev->vgstack[i].dash_pattern, "pdfwrite final free stored dash in gstate");
993c09
+    }
993c09
+
993c09
     cos_release((cos_object_t *)pdev->NI_stack, "Release Name Index stack");
993c09
     gs_free_object(mem, pdev->NI_stack, "Free Name Index stack");
993c09
     pdev->NI_stack = 0;
993c09
diff --git a/base/gdevpdfg.c b/base/gdevpdfg.c
993c09
index 2d4e040..56b24f7 100644
993c09
--- a/base/gdevpdfg.c
993c09
+++ b/base/gdevpdfg.c
993c09
@@ -71,8 +71,19 @@ pdf_save_viewer_state(gx_device_pdf *pdev, stream *s)
993c09
     pdev->vgstack[i].saved_stroke_color = pdev->saved_stroke_color;
993c09
     pdev->vgstack[i].line_params = pdev->state.line_params;
993c09
     pdev->vgstack[i].line_params.dash.pattern = 0; /* Use pdev->dash_pattern instead. */
993c09
-    memcpy(pdev->vgstack[i].dash_pattern, pdev->dash_pattern,
993c09
-                sizeof(pdev->vgstack[i].dash_pattern));
993c09
+    if (pdev->dash_pattern) {
993c09
+        if (pdev->vgstack[i].dash_pattern)
993c09
+            gs_free_object(pdev->memory->non_gc_memory, pdev->vgstack[i].dash_pattern, "free gstate copy dash");
993c09
+        pdev->vgstack[i].dash_pattern = (float *)gs_alloc_bytes(pdev->memory->non_gc_memory, pdev->dash_pattern_size * sizeof(float), "gstate copy dash");
993c09
+        memcpy(pdev->vgstack[i].dash_pattern, pdev->dash_pattern, pdev->dash_pattern_size * sizeof(float));
993c09
+        pdev->vgstack[i].dash_pattern_size = pdev->dash_pattern_size;
993c09
+    } else {
993c09
+        if (pdev->vgstack[i].dash_pattern) {
993c09
+            gs_free_object(pdev->memory->non_gc_memory, pdev->vgstack[i].dash_pattern, "free gstate copy dash");
993c09
+            pdev->vgstack[i].dash_pattern = 0;
993c09
+            pdev->vgstack[i].dash_pattern_size = 0;
993c09
+        }
993c09
+    }
993c09
     pdev->vgstack_depth++;
993c09
     if (s)
993c09
         stream_puts(s, "q\n");
993c09
@@ -106,8 +117,18 @@ pdf_load_viewer_state(gx_device_pdf *pdev, pdf_viewer_state *s)
993c09
     pdev->saved_fill_color = s->saved_fill_color;
993c09
     pdev->saved_stroke_color = s->saved_stroke_color;
993c09
     pdev->state.line_params = s->line_params;
993c09
-    memcpy(pdev->dash_pattern, s->dash_pattern,
993c09
-                sizeof(s->dash_pattern));
993c09
+    if (s->dash_pattern) {
993c09
+        if (pdev->dash_pattern)
993c09
+            gs_free_object(pdev->memory->stable_memory, pdev->dash_pattern, "vector free dash pattern");
993c09
+        pdev->dash_pattern = (float *)gs_alloc_bytes(pdev->memory->stable_memory, s->dash_pattern_size * sizeof(float), "vector allocate dash pattern");
993c09
+        pdev->dash_pattern_size  = s->dash_pattern_size;
993c09
+    } else {
993c09
+        if (pdev->dash_pattern) {
993c09
+            gs_free_object(pdev->memory->stable_memory, pdev->dash_pattern, "vector free dash pattern");
993c09
+            pdev->dash_pattern = 0;
993c09
+            pdev->dash_pattern_size = 0;
993c09
+        }
993c09
+    }
993c09
 }
993c09
 
993c09
 /* Restore the viewer's graphic state. */
993c09
@@ -178,7 +199,8 @@ pdf_viewer_state_from_imager_state_aux(pdf_viewer_state *pvs, const gs_imager_st
993c09
     pvs->line_params.dot_length_absolute = pis->line_params.dot_length_absolute;
993c09
     pvs->line_params.dot_orientation = pis->line_params.dot_orientation;
993c09
     memset(&pvs->line_params.dash, 0 , sizeof(pvs->line_params.dash));
993c09
-    memset(pvs->dash_pattern, 0, sizeof(pvs->dash_pattern));
993c09
+    pvs->dash_pattern = 0;
993c09
+    pvs->dash_pattern_size = 0;
993c09
 }
993c09
 
993c09
 /* Copy viewer state from images state. */
993c09
diff --git a/base/gdevpdfx.h b/base/gdevpdfx.h
993c09
index bc0545d..69a8257 100644
993c09
--- a/base/gdevpdfx.h
993c09
+++ b/base/gdevpdfx.h
993c09
@@ -500,7 +500,8 @@ typedef struct pdf_viewer_state_s {
993c09
     gx_hl_saved_color saved_fill_color;
993c09
     gx_hl_saved_color saved_stroke_color;
993c09
     gx_line_params line_params;
993c09
-    float dash_pattern[max_dash];
993c09
+    float *dash_pattern;
993c09
+    uint dash_pattern_size;
993c09
     gs_id soft_mask_id;
993c09
 } pdf_viewer_state;
993c09
 
993c09
diff --git a/base/gdevvec.c b/base/gdevvec.c
993c09
index ddf787e..ac006f5 100644
993c09
--- a/base/gdevvec.c
993c09
+++ b/base/gdevvec.c
993c09
@@ -457,24 +457,26 @@ gdev_vector_prepare_stroke(gx_device_vector * vdev,
993c09
         float dash_offset = pis->line_params.dash.offset * scale;
993c09
         float half_width = pis->line_params.half_width * scale;
993c09
 
993c09
-        if (pattern_size > max_dash)
993c09
-            return_error(gs_error_limitcheck);
993c09
         if (dash_offset != vdev->state.line_params.dash.offset ||
993c09
             pattern_size != vdev->state.line_params.dash.pattern_size ||
993c09
             (pattern_size != 0 &&
993c09
              !dash_pattern_eq(vdev->dash_pattern, &pis->line_params.dash,
993c09
                               scale))
993c09
             ) {
993c09
-            float pattern[max_dash];
993c09
+            float *pattern;
993c09
             int i, code;
993c09
 
993c09
+            pattern = gs_alloc_bytes(vdev->memory->stable_memory, pattern_size * sizeof(float), "vector allocate dash pattern");
993c09
             for (i = 0; i < pattern_size; ++i)
993c09
                 pattern[i] = pis->line_params.dash.pattern[i] * scale;
993c09
             code = (*vdev_proc(vdev, setdash))
993c09
                 (vdev, pattern, pattern_size, dash_offset);
993c09
             if (code < 0)
993c09
                 return code;
993c09
-            memcpy(vdev->dash_pattern, pattern, pattern_size * sizeof(float));
993c09
+            if (vdev->dash_pattern)
993c09
+                gs_free_object(vdev->memory->stable_memory, vdev->dash_pattern, "vector free old dash pattern");
993c09
+            vdev->dash_pattern = pattern;
993c09
+            vdev->dash_pattern_size = pattern_size;
993c09
 
993c09
             vdev->state.line_params.dash.pattern_size = pattern_size;
993c09
             vdev->state.line_params.dash.offset = dash_offset;
993c09
@@ -816,6 +818,10 @@ gdev_vector_close_file(gx_device_vector * vdev)
993c09
     FILE *f = vdev->file;
993c09
     int err;
993c09
 
993c09
+    if (vdev->dash_pattern) {
993c09
+        gs_free_object(vdev->memory->stable_memory, vdev->dash_pattern, "vector free dash pattern");
993c09
+        vdev->dash_pattern = 0;
993c09
+    }
993c09
     if (vdev->bbox_device) {
993c09
         rc_decrement(vdev->bbox_device->icc_struct, "vector_close(bbox_device->icc_struct");
993c09
         vdev->bbox_device->icc_struct = NULL;
993c09
diff --git a/base/gdevvec.h b/base/gdevvec.h
993c09
index 1a3eece..385e126 100644
993c09
--- a/base/gdevvec.h
993c09
+++ b/base/gdevvec.h
993c09
@@ -66,9 +66,6 @@ typedef struct gx_device_vector_s gx_device_vector;
993c09
 /* Define the maximum size of the output file name. */
993c09
 #define fname_size (gp_file_name_sizeof - 1)
993c09
 
993c09
-/* Define the longest dash pattern we can remember. */
993c09
-#define max_dash 11
993c09
-
993c09
 /*
993c09
  * Define procedures for writing common output elements.  Not all devices
993c09
  * will support all of these elements.  Note that these procedures normally
993c09
@@ -168,7 +165,8 @@ int gdev_vector_dorect(gx_device_vector * vdev, fixed x0, fixed y0,
993c09
         int open_options;	/* see below */\
993c09
                 /* Graphics state */\
993c09
         gs_imager_state state;\
993c09
-        float dash_pattern[max_dash];\
993c09
+        float *dash_pattern;\
993c09
+        uint dash_pattern_size;\
993c09
         bool fill_used_process_color;\
993c09
         bool stroke_used_process_color;\
993c09
         gx_hl_saved_color saved_fill_color;\
993c09
@@ -194,7 +192,8 @@ int gdev_vector_dorect(gx_device_vector * vdev, fixed x0, fixed y0,
993c09
         0,		/* strmbuf_size */\
993c09
         0,		/* open_options */\
993c09
          { 0 },		/* state */\
993c09
-         { 0 },		/* dash_pattern */\
993c09
+        0,      /* dash_pattern */\
993c09
+        0,      /* dash pattern size */\
993c09
         true,		/* fill_used_process_color */\
993c09
         true,		/* stroke_used_process_color */\
993c09
          { 0 },		/* fill_color ****** WRONG ****** */\
993c09
@@ -216,10 +215,10 @@ struct gx_device_vector_s {
993c09
 /* extern its descriptor for the sake of subclasses. */
993c09
 extern_st(st_device_vector);
993c09
 #define public_st_device_vector()	/* in gdevvec.c */\
993c09
-  gs_public_st_suffix_add3_final(st_device_vector, gx_device_vector,\
993c09
+  gs_public_st_suffix_add4_final(st_device_vector, gx_device_vector,\
993c09
     "gx_device_vector", device_vector_enum_ptrs,\
993c09
     device_vector_reloc_ptrs, gx_device_finalize, st_device, strm, strmbuf,\
993c09
-    bbox_device)
993c09
+    dash_pattern, bbox_device)
993c09
 #define st_device_vector_max_ptrs (st_device_max_ptrs + 3)
993c09
 
993c09
 /* ================ Utility procedures ================ */
993c09
-- 
993c09
2.14.3
993c09