Fix for 687555, /rangecheck in --array-- when loading some (large) CMaps

Alex Cherepanov <[email protected]> Sun, 08 Aug 2004 06:12:11 -0400
Newsgroups gmane.comp.printing.ghostscript.patches
Organization Coscript Software
Message-ID <[email protected]>
Use extra level of nesting instead of concatenating CMap data to
accommodate CMap's with >= 64K elements.
Fix bug 587555

This patch should not affect anything except the small increase
in VM use for CMap resources. I'm running the regression test now.

_______________________________________________
gs-code-review mailing list
[email protected]
http://www.ghostscript.com/mailman/listinfo/gs-code-review
687555.diff (text/plain, 8.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	8 Aug 2004 09:55:16 -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,42 +106,52 @@
 % ------ 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 {
-    (*** 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
+    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 {
+    (*** 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
-} bind def
-
 /.endmap {		% <map> .endmap <map>
   dup type /arraytype eq {
 	% This might be a shared read-only array inherited via usecmap.
@@ -164,6 +174,7 @@
 /begincodespacerange {	% <count> begincodespacerange -
   pop mark
 } bind def
+
 /endcodespacerange {	% <code_lo> <code_hi> ... endcodespacerange -
   0 .appendmap
 } bind def
@@ -186,6 +197,7 @@
     /FontMatrices exch def
   } if
 } bind def
+
 /endusematrix {		% <matrix> endusematrix -
   FontMatrices 3 1 roll put
 } bind def
@@ -504,18 +516,18 @@
       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
 /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.14
diff -b -u -r1.14 zfcmap.c
--- gs/src/zfcmap.c	10 Apr 2003 11:58:25 -0000	1.14
+++ gs/src/zfcmap.c	8 Aug 2004 09:55:16 -0000
@@ -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(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(pref, i, &elem);
+        elem_sz = r_size(&elem);
+        for (j = 0; j < elem_sz; j += 2) {
 	ref rfirst, rlast;
 	int size;
 
-	array_get(pref, i * 2L, &rfirst);
-	array_get(pref, i * 2L + 1, &rlast);
+	    array_get(&elem, j, &rfirst);
+	    array_get(&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(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(pref, i, &elem);
+        elem_sz = r_size(&elem);
+        for (j = 0; j < elem_sz; j += 5) {
 	ref rprefix, rmisc, rkeys, rvalues, rfxs;
 
-	array_get(pref, i, &rprefix);
-	array_get(pref, i + 1, &rmisc);
-	array_get(pref, i + 2, &rkeys);
-	array_get(pref, i + 3, &rvalues);
-	array_get(pref, i + 4, &rfxs);
+	    array_get(&elem, j, &rprefix);
+	    array_get(&elem, j + 1, &rmisc);
+	    array_get(&elem, j + 2, &rkeys);
+	    array_get(&elem, j + 3, &rvalues);
+	    array_get(&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;
 }