[gs-code-review] Fix for 687643,
gs crashes on HP-UX 11.23 for Itanium
Alex Cherepanov
alexcher at coscript.com
Tue Sep 14 15:15:51 PDT 2004
Fix handling of special cases during allocation and freeing of ref
arrays when ARCH_ALIGN_STRUCT_MOD > sizeof(ref). This is significant for
HP-UX for Itanium with aC++/C compiler. The problem can be simulated on
PC by editing arch.h.
[COMMENTS]
I didn't test this fix on Itanium yet, just on PC with the arch.h hack.
To avoid any run-time costs on common platforms ptr_align_round()
can be defined as :
#define ptr_align_round(p)\
( ARCH_ALIGN_STRUCT_MOD > size_of_ref ? \
((byte *)obj_align_round((size_t)(p))) : \
(p))
To do so we need to add size_of_ref to arch.h
Do we want this ?
-------------- next part --------------
Index: gs/src/gxalloc.h
===================================================================
RCS file: /cvs/ghostscript/gs/src/gxalloc.h,v
retrieving revision 1.11
diff -b -u -r1.11 gxalloc.h
--- gs/src/gxalloc.h 4 Aug 2004 19:36:12 -0000 1.11
+++ gs/src/gxalloc.h 14 Sep 2004 21:44:37 -0000
@@ -143,7 +143,7 @@
byte *cbot; /* bottom of free area */
/* (top of aligned objects) */
obj_header_t *rcur; /* current refs object, 0 if none */
- byte *rtop; /* top of rcur */
+ byte *rtop; /* top of rcur, not aligned to obj_align_mod */
byte *ctop; /* top of free area */
/* (bottom of strings) */
byte *climit; /* top of strings */
Index: gs/src/gxobj.h
===================================================================
RCS file: /cvs/ghostscript/gs/src/gxobj.h,v
retrieving revision 1.6
diff -b -u -r1.6 gxobj.h
--- gs/src/gxobj.h 21 Feb 2002 22:24:53 -0000 1.6
+++ gs/src/gxobj.h 14 Sep 2004 21:44:37 -0000
@@ -110,20 +110,22 @@
/* The only possible values for obj_align_mod are 4, 8, or 16.... */
#if obj_align_mod == 4
# define log2_obj_align_mod 2
-#else
-#if obj_align_mod == 8
+#elif obj_align_mod == 8
# define log2_obj_align_mod 3
-#else
-#if obj_align_mod == 16
+#elif obj_align_mod == 16
# define log2_obj_align_mod 4
-#endif
-#endif
+#elif obj_align_mod == 32 /* for testing, not seen yet in the wild */
+# define log2_obj_align_mod 5
+#else
+# error Unexpected value of obj_align_mod
#endif
#define obj_align_mask (obj_align_mod-1)
#define obj_align_round(siz)\
(uint)(((siz) + obj_align_mask) & -obj_align_mod)
#define obj_size_round(siz)\
obj_align_round((siz) + sizeof(obj_header_t))
+#define ptr_align_round(p)\
+ ((byte *)obj_align_round((size_t)(p)))
/* Define the real object header type, taking alignment into account. */
struct obj_header_s { /* must be a struct because of forward reference */
Index: gs/src/ialloc.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/ialloc.c,v
retrieving revision 1.7
diff -b -u -r1.7 ialloc.c
--- gs/src/ialloc.c 4 Aug 2004 19:36:12 -0000 1.7
+++ gs/src/ialloc.c 14 Sep 2004 21:44:37 -0000
@@ -157,8 +157,8 @@
/* If we're allocating a run of refs already, */
/* and we aren't about to overflow the maximum run length, use it. */
- if (mem->cc.rtop == mem->cc.cbot &&
- num_refs < (mem->cc.ctop - mem->cc.cbot) / sizeof(ref) &&
+ if (ptr_align_round(mem->cc.rtop) == mem->cc.cbot &&
+ num_refs < (mem->cc.ctop - mem->cc.rtop) / sizeof(ref) &&
mem->cc.rtop - (byte *) mem->cc.rcur + num_refs * sizeof(ref) <
max_size_st_refs
) {
@@ -169,8 +169,8 @@
ialloc_trace_space(mem), client_name_string(cname),
num_refs, (ulong) obj);
mem->cc.rcur[-1].o_size += num_refs * sizeof(ref);
- end = (ref *) (mem->cc.rtop = mem->cc.cbot +=
- num_refs * sizeof(ref));
+ end = (ref *) (mem->cc.rtop += num_refs * sizeof(ref));
+ mem->cc.cbot = ptr_align_round(mem->cc.rtop);
make_mark(end - 1);
} else {
/*
@@ -225,12 +225,12 @@
return_error(e_Fatal);
diff = old_num_refs - new_num_refs;
/* Check for LIFO. See gs_free_ref_array for more details. */
- if (mem->cc.rtop == mem->cc.cbot &&
+ if (ptr_align_round(mem->cc.rtop) == mem->cc.cbot &&
(byte *) (obj + (old_num_refs + 1)) == mem->cc.rtop
) {
/* Shorten the refs object. */
- ref *end = (ref *) (mem->cc.cbot = mem->cc.rtop -=
- diff * sizeof(ref));
+ ref *end = (ref *) (mem->cc.rtop -= diff * sizeof(ref));
+ mem->cc.cbot = ptr_align_round(mem->cc.rtop);
if_debug4('A', "[a%d:<$ ]%s(%u) 0x%lx\n",
ialloc_trace_space(mem), client_name_string(cname), diff,
@@ -264,7 +264,7 @@
*/
if (!r_has_type(parr, t_array))
DO_NOTHING; /* don't look for special cases */
- else if (mem->cc.rtop == mem->cc.cbot &&
+ else if (ptr_align_round(mem->cc.rtop) == mem->cc.cbot &&
(byte *) (obj + (num_refs + 1)) == mem->cc.rtop
) {
if ((obj_header_t *) obj == mem->cc.rcur) {
@@ -278,7 +278,8 @@
ialloc_trace_space(mem), client_name_string(cname),
num_refs, (ulong) obj);
mem->cc.rcur[-1].o_size -= num_refs * sizeof(ref);
- mem->cc.rtop = mem->cc.cbot = (byte *) (obj + 1);
+ mem->cc.rtop = (byte *) (obj + 1);
+ mem->cc.cbot = ptr_align_round(mem->cc.rtop);
make_mark(obj);
}
return;
Index: gs/src/igcref.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/igcref.c,v
retrieving revision 1.6
diff -b -u -r1.6 igcref.c
--- gs/src/igcref.c 4 Aug 2004 19:36:12 -0000 1.6
+++ gs/src/igcref.c 14 Sep 2004 21:44:37 -0000
@@ -720,15 +720,18 @@
new_size += sizeof(ref_packed);
/* We want to make the newly freed space into a free block, */
/* but we can only do this if we have enough room. */
- if (size - new_size < sizeof(obj_header_t)) { /* Not enough room. Pad to original size. */
+ if (size < obj_align_round(new_size) + sizeof(obj_header_t)) { /* Not enough room. Pad to original size. */
while (new_size < size)
*dest++ = pt_tag(pt_integer),
new_size += sizeof(ref_packed);
} else {
- obj_header_t *pfree = (obj_header_t *) ((ref *) dest + 1);
+ byte *pfree_u = (byte *)dest + sizeof(ref);
+ byte *pfree_a = ptr_align_round(pfree_u);
+ obj_header_t *pfree = (obj_header_t *)pfree_a;
+ int align = pfree_a - pfree_u;
pfree->o_alone = 0;
- pfree->o_size = size - new_size - sizeof(obj_header_t);
+ pfree->o_size = size - new_size - sizeof(obj_header_t) - align;
pfree->o_type = &st_bytes;
}
/* Re-create the final ref. */
More information about the gs-code-review
mailing list