[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