Changed parse_subrs() so that it'll work correctly both with wrongly sorted subr indices *and* non-contiguous subr arrays. Thanks to Tom K. for helping to isolate the problem.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
diff --git a/src/type1z/z1load.c b/src/type1z/z1load.c
index f860306..aaa891a 100644
--- a/src/type1z/z1load.c
+++ b/src/type1z/z1load.c
@@ -1243,6 +1243,11 @@
if ( parser->error )
return;
+ /* position the parser right before the "dup" of the first subr */
+ skip_whitespace( parser );
+ skip_blackspace( parser ); /* "array" */
+ skip_whitespace( parser );
+
/* initialize subrs array */
error = Z1_New_Table( table, loader->num_subrs, memory );
if ( error )
@@ -1259,17 +1264,29 @@
FT_Byte* base;
+ /* If the next token isn't "dup", we're also done. This */
+ /* happens when there are "holes" in the Subrs array. */
+ if ( strncmp( (char*)parser->cursor, "dup", 3 ) != 0 )
+ break;
+
index = Z1_ToInt( parser );
- /* make sure we get subr index and loop count in sync -- */
- /* in some cases, the dictionary count is simply the last */
- /* subr index + 1, with possible holes in the table */
- if ( index > n )
- n = index;
-
if ( !read_binary_data( parser, &size, &base ) )
return;
+ /* The binary string is followed by one token, eg. "NP" */
+ /* (bound to "noaccess put") or by two separate tokens: */
+ /* "noaccess" & "put". We position the parser right */
+ /* before the next dup, if any. */
+ skip_whitespace( parser );
+ skip_blackspace( parser ); /* "NP" or "I" or "noaccess" */
+ skip_whitespace( parser );
+ if ( strncmp( (char*)parser->cursor, "put", 3 ) == 0 )
+ {
+ skip_blackspace( parser ); /* skip "put" */
+ skip_whitespace( parser );
+ }
+
/* some fonts use a value of -1 for lenIV to indicate that */
/* the charstrings are unencoded.. */
/* */