Fix for 687555, /rangecheck in --array-- when loading some (large) CMaps, 3rd version
Alex Cherepanov <[email protected]> Wed, 01 Sep 2004 01:12:48 -0400
| Newsgroups | gmane.comp.printing.ghostscript.patches |
|---|---|
| Organization | Coscript Software |
| Message-ID | <[email protected]> |
[LOG MESSAGE] Use extra level of nested arrays instead of concatenating CMap data in a single array to accommodate CMap's with >= 64K elements. Work around bugs in Adobe-CNS1-ETen-B5 and Adobe-Korea1-H-Mac files. Fix bug 587555 [DETAILS] Adobe-CNS1-ETen-B5 file defines Adobe-CNS1-ETenms-B5 resource which caused /undefined resource error. For this file the patch changes CMapName back to Adobe-CNS1-ETen-B5. A new CMap file Adobe-CNS1-ETenms-B5 is added to the CMap collection. /Adobe-Korea1-H-Mac failed with /undefined in endcmap because the file has a duplicate trailer. The patch recognizes the offending file and skips the duplicate code. [COMMENTS] Re Igor's suggestion to use the dictionary I can take a look into the issue. Hoverer, the internal representation of the CMap doesn't need to be similar to CMap resource. We can optimize the latter in C but leave the former unchanged. _______________________________________________ gs-code-review mailing list [email protected] http://www.ghostscript.com/mailman/listinfo/gs-code-review
687555c.diff
(text/plain, 9.4 KB)
Index: gs/lib/gs_cmap.ps
===================================================================
RCS file: /cvs/ghostscript/gs/lib/gs_cmap.ps,v
retrieving revision 1.17
diff -b -u -r1.17 gs_cmap.ps
--- gs/lib/gs_cmap.ps 12 Apr 2003 18:08:18 -0000 1.17
+++ gs/lib/gs_cmap.ps 1 Sep 2004 04:36:42 -0000
@@ -22,7 +22,7 @@
[
/CMERGE_DEBUG
/USE_CIDCHAR_AS_RANGE
-] {dup where {pop pop} { currentdict exch false def pop } ifelse} forall
+] {dup where {pop pop} { currentdict exch //false def pop } ifelse} forall
% ---------------- Public operators ---------------- %
@@ -65,7 +65,7 @@
} ifelse findresource
} if
exch CMap /FontMatrices get dup length 2 index gt {
- exch get dup null eq { pop } { makefont } ifelse
+ exch get dup //null eq { pop } { makefont } ifelse
} {
pop pop
} ifelse
@@ -85,9 +85,9 @@
% Our internal .CodeMapData structure closely mirrors the structures
% defined in gxfcmap.h (q.v.). () indicate a string, [] indicate an array,
% ? indicates a Boolean, # indicates an integer, {} for grouping.
-% [[(first) (last) ...] % code space ranges
-% [(prefix) (key_size,?is_range,value_type,value_size) (keys...)
-% {(values...) | [value ...]} #font_index % code mappings
+% [[[(first) (last) ...]+] % code space ranges
+% [[(prefix) (key_size,?is_range,value_type,value_size) (keys...)
+% {(values...) | [value ...]} #font_index ]+] % code mappings
% ...]
% <<same>> % notdef mappings
% ]
@@ -106,40 +106,68 @@
% ------ Font-level operators ------ %
/begincmap { % - begincmap -
- /.CodeMapData [[] [] []] def
+ /.CodeMapData [[[]] [[]] [[]]] def
/FontMatrices [] def
/.FontIndex 0 def
/.TempMaps [20 dict 50 dict 50 dict] def
- /CodeMap null def % for .buildcmap
+ /CodeMap //null def % for .buildcmap
} bind def
+
/endcmap { % - endcmap -
.rewriteTempMapsNotDef
+
+ CMAPDEBUG {
+ 2 (*** undefined charmap ***)
+ 1 (*** defined charmap ***)
+ 0 (*** code space ranges ***)
+ 3 { =
+ .TempMaps exch get
+ 0 1 2 index length 1 sub {
+ dup == (\t) print
+ 1 index exch get ==
+ } for
+ pop
+ } repeat
+ } if
+
+ /.CodeMapData dup load [ exch
+ .TempMaps aload pop begin begin begin
+ {
+ [ exch aload pop
+ 0 1 currentdict length 1 sub {
+ currentdict exch get
+ } for
+ ]
+ end
+ } forall
+ ] .endmap def
+
CMAPDEBUG {
- (*** defined charmap ***\n) print
- .TempMaps 1 get {exch == (\t) print ==} forall
- (*** undefined charmap ***\n) print
- .TempMaps 2 get {exch == (\t) print ==} forall
- } if
- 10 dict begin 0 1 2 {
- /i exch def
- % Append data from .TempMaps to .CodeMapData.
- /t .TempMaps i get def
- .CodeMapData i get length t { exch pop length add } forall
- CMAPDEBUG { (requested array size ) print dup == } if
- array /a exch def
- a 0 .CodeMapData i get .putmore
- 0 1 t length 1 sub {
- t exch get .putmore
- } for pop pop
- .CodeMapData i a put
- } for end
+ (*** Content of .CodeMapData ***) =
+ 0 .CodeMapData { exch dup == 1 add exch (\t) print == } forall
+ pop
+ } if
+
currentdict /.TempMaps undef
- /.CodeMapData .CodeMapData .endmap def
/FontMatrices FontMatrices .endmap def
-} bind def
-/.putmore { % <array> <i> <array2> .putmore <array> <i+len(array2)>
- 3 copy putinterval length add
+ % Fix Adobe-CNS1-ETen-B5 file that defines Adobe-CNS1-ETenms-B5 CMap
+ currentdict /CMapName .knownget {
+ /Adobe-CNS1-ETenms-B5 eq {
+ currentdict /XUID .knownget {
+ dup length 4 eq {
+ 1212 25335 10 1 //true
+ 6 -1 roll { 3 -1 roll eq and } forall {
+ /CMapName /Adobe-CNS1-ETen-B5 def
+ } if
+ } {
+ pop
+ } ifelse
+ } if
+ } if
+ } if
+
+
} bind def
/.endmap { % <map> .endmap <map>
@@ -164,6 +192,7 @@
/begincodespacerange { % <count> begincodespacerange -
pop mark
} bind def
+
/endcodespacerange { % <code_lo> <code_hi> ... endcodespacerange -
0 .appendmap
} bind def
@@ -186,6 +215,7 @@
/FontMatrices exch def
} if
} bind def
+
/endusematrix { % <matrix> endusematrix -
FontMatrices 3 1 roll put
} bind def
@@ -504,18 +534,28 @@
dup length dict .copydict exch .setglobal
} if
dup gcheck 2 index gcheck not and {
- exch .currentglobal exch true .setglobal
+ exch .currentglobal exch //true .setglobal
dup length string copy exch .setglobal exch
} if dup /CMapName 3 index put
} if
- dup /CodeMap get null eq { .buildcmap } if
+ dup /CodeMap get //null eq { .buildcmap } if
/Generic /Category findresource /DefineResource get exec
-} put
+
+ % Skip duplicate trailer in /Adobe-Korea1-H-Mac
+ dup /CMapName get /Adobe-Korea1-H-Mac eq {
+ currentfile 128 string .peekstring pop
+ (CMapName currentdict /CMap defineresource) search {
+ 2 { currentfile exch readstring pop pop } repeat
+ } if
+ pop
+ } if
+
+} bind put
/Category defineresource pop
% We might have loaded CID font support already.
/CIDInit /ProcSet 2 copy { findresource } .internalstopped
% An interior `stopped' might have reset VM allocation to local.
-true .setglobal
+//true .setglobal
{ pop pop 3 -1 roll }
{ dup length 4 index length add dict .copydict 4 -1 roll exch .copydict }
ifelse exch defineresource pop
Index: gs/src/zfcmap.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/zfcmap.c,v
retrieving revision 1.15
diff -b -u -r1.15 zfcmap.c
--- gs/src/zfcmap.c 4 Aug 2004 19:36:13 -0000 1.15
+++ gs/src/zfcmap.c 1 Sep 2004 04:36:42 -0000
@@ -14,7 +14,7 @@
San Rafael, CA 94903, U.S.A., +1(415)492-9861.
*/
-/* $Id: zfcmap.c,v 1.15 2004/08/04 19:36:13 stefan Exp $ */
+/* $Id: zfcmap.c,v 1.14 2003/04/10 11:58:25 igor Exp $ */
/* CMap creation operator */
#include "memory_.h"
#include "ghost.h"
@@ -63,14 +63,26 @@
private int
acquire_code_ranges(gs_cmap_adobe1_t *cmap, const ref *pref, gs_memory_t *mem)
{
- uint num_ranges;
+ uint num_ranges = 0;
gx_code_space_range_t *ranges;
- uint i;
+ uint i, j, elem_sz;
+ ref elem;
- if (!r_is_array(pref) || (num_ranges = r_size(pref)) == 0 ||
- num_ranges & 1)
+ if (!r_is_array(pref))
+ return_error(e_rangecheck);
+ for (i=0; i < r_size(pref); i++) {
+ int code = array_get(mem, pref, i, &elem);
+ if (code < 0)
+ return code;
+ elem_sz = r_size(&elem);
+ if (elem_sz & 1)
+ return_error(e_rangecheck);
+ num_ranges += elem_sz;
+ }
+ if (num_ranges == 0)
return_error(e_rangecheck);
num_ranges >>= 1;
+
ranges = (gx_code_space_range_t *)
gs_alloc_byte_array(mem, num_ranges, sizeof(gx_code_space_range_t),
"acquire_code_ranges");
@@ -78,12 +90,16 @@
return_error(e_VMerror);
cmap->code_space.ranges = ranges;
cmap->code_space.num_ranges = num_ranges;
- for (i = 0; i < num_ranges; ++i, ++ranges) {
+
+ for (i = 0; i < r_size(pref); i++) {
+ array_get(mem, pref, i, &elem);
+ elem_sz = r_size(&elem);
+ for (j = 0; j < elem_sz; j += 2) {
ref rfirst, rlast;
int size;
- array_get(mem, pref, i * 2L, &rfirst);
- array_get(mem, pref, i * 2L + 1, &rlast);
+ array_get(mem, &elem, j, &rfirst);
+ array_get(mem, &elem, j + 1, &rlast);
if (!r_has_type(&rfirst, t_string) ||
!r_has_type(&rlast, t_string) ||
(size = r_size(&rfirst)) == 0 || size > MAX_CMAP_CODE_SIZE ||
@@ -93,6 +109,8 @@
memcpy(ranges->first, rfirst.value.bytes, size);
memcpy(ranges->last, rlast.value.bytes, size);
ranges->size = size;
+ ++ranges;
+ }
}
return 0;
}
@@ -102,12 +120,23 @@
acquire_code_map(gx_code_map_t *pcmap, const ref *pref, gs_cmap_adobe1_t *root,
gs_memory_t *mem)
{
- uint num_lookup;
+ uint num_lookup = 0;
gx_cmap_lookup_range_t *pclr;
long i;
+ ref elem;
+ uint elem_sz;
- if (!r_is_array(pref) || (num_lookup = r_size(pref)) % 5 != 0)
+ if (!r_is_array(pref))
+ return_error(e_rangecheck);
+ for (i=0; i < r_size(pref); i++) {
+ int code = array_get(mem, pref, i, &elem);
+ if (code < 0)
+ return code;
+ elem_sz = r_size(&elem);
+ if (elem_sz % 5 != 0)
return_error(e_rangecheck);
+ num_lookup += elem_sz;
+ }
num_lookup /= 5;
pclr = gs_alloc_struct_array(mem, num_lookup, gx_cmap_lookup_range_t,
&st_cmap_lookup_range_element,
@@ -117,14 +146,20 @@
memset(pclr, 0, sizeof(*pclr) * num_lookup);
pcmap->lookup = pclr;
pcmap->num_lookup = num_lookup;
- for (i = 0; i < num_lookup * 5; i += 5, ++pclr) {
+
+
+ for (i = 0; i < r_size(pref); i++) {
+ uint j;
+ array_get(mem, pref, i, &elem);
+ elem_sz = r_size(&elem);
+ for (j = 0; j < elem_sz; j += 5) {
ref rprefix, rmisc, rkeys, rvalues, rfxs;
- array_get(mem, pref, i, &rprefix);
- array_get(mem, pref, i + 1, &rmisc);
- array_get(mem, pref, i + 2, &rkeys);
- array_get(mem, pref, i + 3, &rvalues);
- array_get(mem, pref, i + 4, &rfxs);
+ array_get(mem, &elem, j, &rprefix);
+ array_get(mem, &elem, j + 1, &rmisc);
+ array_get(mem, &elem, j + 2, &rkeys);
+ array_get(mem, &elem, j + 3, &rvalues);
+ array_get(mem, &elem, j + 4, &rfxs);
if (!r_has_type(&rprefix, t_string) ||
!r_has_type(&rmisc, t_string) ||
@@ -206,6 +241,8 @@
}
check_int_leu_only(rfxs, 0xff);
pclr->font_index = (int)rfxs.value.intval;
+ ++pclr;
+ }
}
return 0;
}
Adobe-CNS1-ETenms-B5
(application/postscript, 1.1 KB) - not displayed