[gs-cvs] gs/src

Dan Coby dan at casper.ghostscript.com
Thu Sep 26 11:45:04 PDT 2002


Update of /cvs/ghostscript/gs/src
In directory casper:/tmp/cvs-serv7908/src

Modified Files:
	gsht.c gsht1.c gspaint.c gspath.c gxclrast.c gxpath.c zfdcte.c 
Log Message:
The attached code release fixes a variety of memory handling problems
discovered by Dan's test with the memory validation enabled.

  1. Most of the problems with the FTS were accounted for by a relatively
     harmless dangling pointer problem for paths. In order to support the
     charpath operator, paths are normally constructed in stable memory
     (not subject to save/restore). However, clipping paths were
     constructed in normal memory. If the clippath operator was used to
     make the clipping path the current path, the top-level
     gx_path_segments would be in stable memory, while the rest of the
     path would be in normal memory. A restore operation could then
     leave dangling pointers.

     This is not normally a problem, because the grestore operation
     associated with the restore would clear the gx_path_segments
     structure. This only works on the graphic state stack, however;
     graphic state objects stored in VM would not be reset.

     This is harmful only in a very obscure case when the charpath operator
     is used on a user-defined font whose BuildGlyph procedure contains
     internal save/restore operators and which builds part of its
     output with the clippath operator. As far as we know, this has
     never occurred in practice.

  2. Several problems noted with files 119-01.ps (panel 119-07) and
     119-28.ps (panel 119-31) were caused by a problem with the memory
     allocator used for the jpeg_compress_data structure used with the
     DCTEncode (JPEG) filter. This filter is used by the PDFwriter, the
     JPEG device drive, and as a filter accessible from PostScript.
     In the first two cases the jpeg_compress_data structure is allocated
     using the normal, gs_ref_memory_t structure. When used from
     PostScript, however, this structure is allocated using the
     gs_memory_default allocator (presumably because the jpeg library
     code is not set up to deal with save/restore).

     The gs_memory_default allocator is not a gs_ref_memory_t allocator,
     so it does not create the hidden obj_header_t structures preceding
     each allocated region. The garbage collector is dependent on these
     headers, hence the pointer enumeration routines in structure
     descriptors must not enumerate any pointers to memory allocated
     by non-gs_ref_memory_t headers.

     This creates a difficult problem for the pointer enumeration
     routine of the stream_DCT_state structure, whose data.compress field
     points to a jpeg_compress_data structure. This routine would have
     to determine which allocator was used for this structure before
     deciding whether or not to "enumerate" the data.compress pointer.
     In principle it has enough information to do this (the jpeg_memory
     field of the structure), but this seems like a overly complicated
     solution. Use of a stable gs_ref_memory_t allocator in place of
     the gs_memory_default allocator seems like a simpler solution.

  3. If an overprint compositor was used with a banding device, the code
     in clist_playback_band was not cleaning up this compositor before
     exiting. This caused difficulty with the p2b-100.pdf file. This
     code has been modified to close the target device if this device
     does not match the original target device with which the routine
     was invoked.

  4. For historical reasons, the link between a halftone order and its
     tile cache is a bit peculiar. The order includes a pointer to the
     tile cache, and the tile cache keeps a copy of the order, which
     points to the same levels/bit data structure of the original order.
     Because of these two-way points, the order and its tile cache must
     use the same memory allocator to avoid dangling pointer problems.
     The code patch modifies gx_imager_dev_ht_install (gsht.c) to
     preserve this invariant. The change fixes another problem noted for
     p2b-100.pdf.

With these changes, we are able to run both the PS3 FTS and the full set
of pdf regression files using the '-Z@$?' switch with no reported problems.


                                                       Jan

Modified files:

  src/gspaint.c
  src/gspath.c
    In gs_strokepath and gs_clippath, cause the newly constructed path to
    use the memory allocator of the current path, rather than the memory
    of the current graphic state. This is no longer strictly necessary
    due to other changes that place path substructure completely in
    stable memory (see gxpath.c below). 

  src/gxpath.c
    Modify path_allocs_segments, rc_free_path_segments_local,
    gx_path_add_lines_notes, and the path_alloc_segment macro to place
    the entire path substructure (from the gx_path_segments structure
    down) in stable memory. This is necessary to avoid dangling
    pointers, as a list of path segments may be attached to another path,
    parts of which were constructed with a different allocator.

  src/zfdcte.c
    Modified zDCTE to place the jpeg_compress_data structure into stable
    memory rather than use the gs_memory_default allocator.

  src/gsht1.c
    Removed obsolete code.

  src/gxclrast.c
    In clist_playback_band, close and discard the target device on
    completion of a band if it is not the same as the target device on
    entry.  This is necessary to remove an overprint compositor that
    may have been created in the course of the band.

  src/gsht.c
    In gx_imager_dev_ht_install, copy any halftone orders that were not
    allocated using the same allocator as used by the graphic state. This
    must be done to avoid dangling forward/back pointer between halftone
    orders and the associated tile caches.


Index: gsht.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gsht.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- gsht.c	23 Sep 2002 21:36:31 -0000	1.12
+++ gsht.c	26 Sep 2002 18:45:02 -0000	1.13
@@ -938,6 +938,7 @@
     int                     lcm_width = 1, lcm_height = 1;
     gs_wts_screen_enum_t *  wse0 = pdht->order.wse;
     wts_screen_t *          wts0 = 0;
+    bool                    mem_diff = pdht->rc.memory != pis->memory;
 
     /* construct the new device halftone structure */
     memset(&dht.order, 0, sizeof(dht.order));
@@ -970,7 +971,7 @@
     if (pdht->components != 0) {
         int     input_ncomps = pdht->num_comp;
 
-        for (i = 0; i < input_ncomps; i++) {
+        for (i = 0; i < input_ncomps && code >= 0; i++) {
             gx_ht_order_component * p_s_comp = &pdht->components[i];
             gx_ht_order *           p_s_order = &p_s_comp->corder;
             int                     comp_num = p_s_comp->comp_number;
@@ -981,11 +982,21 @@
                 /* indicate that this order has been filled in */
                 dht.components[comp_num].comp_number = comp_num;
 
-                /* check if this is also the default component */
-                used_default = used_default ||
-                               p_s_order->bit_data == pdht->order.bit_data;
+                /*
+                 * The component can be used only if it is from the
+                 * proper memory
+                 */
+                if (mem_diff)
+                    code = gx_ht_copy_ht_order( p_d_order,
+                                                p_s_order,
+                                                pis->memory );
+                else {
+                    /* check if this is also the default component */
+                    used_default = used_default ||
+                                   p_s_order->bit_data == pdht->order.bit_data;
 
-                gx_ht_move_ht_order(p_d_order, p_s_order);
+                    gx_ht_move_ht_order(p_d_order, p_s_order);
+                }
             }
         }
     }
@@ -1025,7 +1036,7 @@
         gs_wts_screen_enum_t *  wse;
 
         if (dht.components[i].comp_number != i) {
-            if (used_default)
+            if (used_default || mem_diff)
                 code = gx_ht_copy_ht_order(porder, &pdht->order, pis->memory);
             else {
                 gx_ht_move_ht_order(porder, &pdht->order);

Index: gsht1.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gsht1.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- gsht1.c	26 Aug 2002 23:07:00 -0000	1.10
+++ gsht1.c	26 Sep 2002 18:45:02 -0000	1.11
@@ -303,22 +303,6 @@
 		    }
 		    if (code < 0)
 			break;
-#if 0
-		    if (poc != pocs) {
-			gx_ht_cache *pcache =
-			gx_ht_alloc_cache(mem, 4,
-					  poc->corder.raster *
-					  (poc->corder.num_bits /
-					   poc->corder.width) * 4);
-
-			if (pcache == 0) {
-			    code = gs_note_error(gs_error_VMerror);
-			    break;
-			}
-			poc->corder.cache = pcache;
-			gx_ht_init_cache(pcache, &poc->corder);
-		    }
-#endif
 		}
 		if (code < 0)
 		    break;

Index: gspaint.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gspaint.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- gspaint.c	21 Feb 2002 22:24:52 -0000	1.4
+++ gspaint.c	26 Sep 2002 18:45:02 -0000	1.5
@@ -377,7 +377,7 @@
     gx_path spath;
     int code;
 
-    gx_path_init_local(&spath, pgs->memory);
+    gx_path_init_local(&spath, pgs->path->memory);
     code = gx_stroke_add(pgs->path, &spath, pgs);
     if (code < 0) {
 	gx_path_free(&spath, "gs_strokepath");

Index: gspath.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gspath.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- gspath.c	16 Jun 2002 05:48:55 -0000	1.6
+++ gspath.c	26 Sep 2002 18:45:02 -0000	1.7
@@ -380,7 +380,7 @@
     gx_path cpath;
     int code;
 
-    gx_path_init_local(&cpath, pgs->memory);
+    gx_path_init_local(&cpath, pgs->path->memory);
     code = gx_cpath_to_path(pgs->clip_path, &cpath);
     if (code >= 0)
 	code = gx_path_assign_free(pgs->path, &cpath);

Index: gxclrast.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gxclrast.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- gxclrast.c	19 Sep 2002 18:36:03 -0000	1.23
+++ gxclrast.c	26 Sep 2002 18:45:02 -0000	1.24
@@ -296,6 +296,7 @@
     int data_x;
     int code = 0;
     ht_buff_t  ht_buff;
+    gx_device *const orig_target = target;
 
     cbuf.data = (byte *)cbuf_storage;
     cbuf.size = cbuf_size;
@@ -1507,6 +1508,11 @@
     gx_path_free(&path, "clist_render_band exit");
     gs_imager_state_release(&imager_state);
     gs_free_object(mem, data_bits, "clist_playback_band(data_bits)");
+    if (target != orig_target) {
+        dev_proc(target, close_device)(target);
+	gs_free_object(target->memory, target, "gxclrast discard compositor");
+	target = orig_target;
+    }
     if (code < 0)
 	return_error(code);
     /* Check whether we have more pages to process. */

Index: gxpath.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gxpath.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- gxpath.c	23 Sep 2002 16:38:28 -0000	1.7
+++ gxpath.c	26 Sep 2002 18:45:02 -0000	1.8
@@ -81,6 +81,7 @@
 path_alloc_segments(gx_path_segments ** ppsegs, gs_memory_t * mem,
 		    client_name_t cname)
 {
+    mem = gs_memory_stable(mem);
     rc_alloc_struct_1(*ppsegs, gx_path_segments, &st_path_segments,
 		      mem, return_error(gs_error_VMerror), cname);
     (*ppsegs)->rc.free = rc_free_path_segments;
@@ -361,6 +362,7 @@
     gx_path_segments *psegs = (gx_path_segments *) vpsegs;
     segment *pseg;
 
+    mem = gs_memory_stable(mem);
     if (psegs->contents.subpath_first == 0)
 	return;			/* empty path */
     pseg = (segment *) psegs->contents.subpath_current->last;
@@ -410,7 +412,8 @@
 #define path_alloc_segment(pseg,ctype,pstype,stype,snotes,cname)\
   path_unshare(ppath);\
   psub = ppath->current_subpath;\
-  if( !(pseg = gs_alloc_struct(ppath->memory, ctype, pstype, cname)) )\
+  if( !(pseg = gs_alloc_struct(gs_memory_stable(ppath->memory), ctype,\
+			       pstype, cname)) )\
     return_error(gs_error_VMerror);\
   pseg->type = stype, pseg->notes = snotes, pseg->next = 0
 #define path_alloc_link(pseg)\
@@ -616,8 +619,9 @@
 	    code = gs_note_error(gs_error_rangecheck);
 	    break;
 	}
-	if (!(next = gs_alloc_struct(ppath->memory, line_segment,
-				     &st_line, "gx_path_add_lines"))
+	if (!(next = gs_alloc_struct(gs_memory_stable(ppath->memory),
+				     line_segment, &st_line,
+				     "gx_path_add_lines"))
 	    ) {
 	    code = gs_note_error(gs_error_VMerror);
 	    break;

Index: zfdcte.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/zfdcte.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- zfdcte.c	21 Feb 2002 22:24:54 -0000	1.7
+++ zfdcte.c	26 Sep 2002 18:45:02 -0000	1.8
@@ -43,7 +43,7 @@
 zDCTE(i_ctx_t *i_ctx_p)
 {
     os_ptr op = osp;
-    gs_memory_t *mem = &gs_memory_default;
+    gs_memory_t *mem = gs_memory_stable(imemory);
     stream_DCT_state state;
     dict_param_list list;
     jpeg_compress_data *jcdp;




More information about the gs-cvs mailing list