ref: bd4b8976a36fd49dc2e04516aa76687c784c4c3a
parent: 1caf629eef20c5809a73f79ce6e2ffc885f125e6
author: Werner Lemberg <[email protected]>
date: Sun Dec 20 14:36:04 EST 2015
[type1, psaux] Handle large values of num_subrs correctly (#46692). We now use a hash to map from subr indices to array elements holding the subroutines, if necessary. * include/freetype/internal/t1types.h: Include FT_INTERNAL_HASH_H. (T1_FontRec): Add `subrs_hash' field. * include/freetype/internal/psaux.h: Include FT_INTERNAL_HASH_H. (T1_DecoderRec): Add `subrs_hash' field. * src/type1/t1load.h (T1_LoaderRec): Add `subrs_hash' field. * src/type1/t1driver.c: Include FT_INTERNAL_HASH_H. (t1_ps_get_font_value) [PS_DICT_SUBR]: Look up hash if necessary. * src/type1/t1load.c: Include FT_INTERNAL_HASH_H. (parse_subrs): Use hash for subr indices that exceed the allocated number of subr slots. (t1_init_loader): Remove unnecessary code. (t1_done_loader, T1_Open_Face): Updated. * src/type1/t1gload.c (T1_Compute_Max_Advance, T1_Get_Advances, T1_Load_Glyph): Updated. * src/type1/t1objs.c (T1_Face_Done): Updated. * src/psaux/t1decode.c: Include FT_INTERNAL_HASH_H. (t1_decoder_parse_charstrings) [op_callsubr]: Look up hash if necessary. * src/cid/cidgload.c (cid_load_glyph): Updated.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,40 @@
2015-12-20 Werner Lemberg <[email protected]>
+ [type1, psaux] Handle large values of num_subrs correctly (#46692).
+
+ We now use a hash to map from subr indices to array elements holding
+ the subroutines, if necessary.
+
+ * include/freetype/internal/t1types.h: Include FT_INTERNAL_HASH_H.
+ (T1_FontRec): Add `subrs_hash' field.
+
+ * include/freetype/internal/psaux.h: Include FT_INTERNAL_HASH_H.
+ (T1_DecoderRec): Add `subrs_hash' field.
+
+ * src/type1/t1load.h (T1_LoaderRec): Add `subrs_hash' field.
+
+ * src/type1/t1driver.c: Include FT_INTERNAL_HASH_H.
+ (t1_ps_get_font_value) [PS_DICT_SUBR]: Look up hash if necessary.
+
+ * src/type1/t1load.c: Include FT_INTERNAL_HASH_H.
+ (parse_subrs): Use hash for subr indices that exceed the allocated
+ number of subr slots.
+ (t1_init_loader): Remove unnecessary code.
+ (t1_done_loader, T1_Open_Face): Updated.
+
+ * src/type1/t1gload.c (T1_Compute_Max_Advance, T1_Get_Advances,
+ T1_Load_Glyph): Updated.
+
+ * src/type1/t1objs.c (T1_Face_Done): Updated.
+
+ * src/psaux/t1decode.c: Include FT_INTERNAL_HASH_H.
+ (t1_decoder_parse_charstrings) [op_callsubr]: Look up hash if
+ necessary.
+
+ * src/cid/cidgload.c (cid_load_glyph): Updated.
+
+2015-12-20 Werner Lemberg <[email protected]>
+
[base] Thinko: Remove free function pointer.
We don't copy keys or values while hashing.
--- a/include/freetype/internal/psaux.h
+++ b/include/freetype/internal/psaux.h
@@ -24,6 +24,7 @@
#include <ft2build.h>
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_TYPE1_TYPES_H
+#include FT_INTERNAL_HASH_H
#include FT_SERVICE_POSTSCRIPT_CMAPS_H
@@ -678,6 +679,7 @@
FT_Int num_subrs;
FT_Byte** subrs;
FT_UInt* subrs_len; /* array of subrs length (optional) */
+ FT_Hash subrs_hash; /* used if `num_subrs' was massaged */
FT_Matrix font_matrix;
FT_Vector font_offset;
--- a/include/freetype/internal/t1types.h
+++ b/include/freetype/internal/t1types.h
@@ -25,6 +25,7 @@
#include FT_TYPE1_TABLES_H
#include FT_INTERNAL_POSTSCRIPT_HINTS_H
#include FT_INTERNAL_SERVICE_H
+#include FT_INTERNAL_HASH_H
#include FT_SERVICE_POSTSCRIPT_CMAPS_H
@@ -107,6 +108,7 @@
FT_Int num_subrs;
FT_Byte** subrs;
FT_UInt* subrs_len;
+ FT_Hash subrs_hash;
FT_Int num_glyphs;
FT_String** glyph_names; /* array of glyph names */
--- a/src/cid/cidgload.c
+++ b/src/cid/cidgload.c
@@ -142,9 +142,10 @@
/* Set up subrs */
- decoder->num_subrs = cid_subrs->num_subrs;
- decoder->subrs = cid_subrs->code;
- decoder->subrs_len = 0;
+ decoder->num_subrs = cid_subrs->num_subrs;
+ decoder->subrs = cid_subrs->code;
+ decoder->subrs_len = 0;
+ decoder->subrs_hash = NULL;
/* Set up font matrix */
dict = cid->font_dicts + fd_select;
--- a/src/psaux/t1decode.c
+++ b/src/psaux/t1decode.c
@@ -20,6 +20,7 @@
#include FT_INTERNAL_CALC_H
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_POSTSCRIPT_HINTS_H
+#include FT_INTERNAL_HASH_H
#include FT_OUTLINE_H
#include "t1decode.h"
@@ -1348,6 +1349,19 @@
FT_TRACE4(( " callsubr" ));
idx = Fix2Int( top[0] );
+
+ if ( decoder->subrs_hash )
+ {
+ size_t* val = ft_hash_num_lookup( idx,
+ decoder->subrs_hash );
+
+
+ if ( val )
+ idx = *val;
+ else
+ idx = -1;
+ }
+
if ( idx < 0 || idx >= decoder->num_subrs )
{
FT_ERROR(( "t1_decoder_parse_charstrings:"
--- a/src/type1/t1driver.c
+++ b/src/type1/t1driver.c
@@ -29,6 +29,7 @@
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_HASH_H
#include FT_SERVICE_MULTIPLE_MASTERS_H
#include FT_SERVICE_GLYPH_DICT_H
@@ -329,13 +330,36 @@
break;
case PS_DICT_SUBR:
- if ( idx < (FT_UInt)type1->num_subrs )
{
- retval = type1->subrs_len[idx] + 1;
- if ( value && value_len >= retval )
+ FT_Bool ok = 0;
+
+
+ if ( type1->subrs_hash )
{
- ft_memcpy( value, (void *)( type1->subrs[idx] ), retval - 1 );
- ((FT_Char *)value)[retval - 1] = (FT_Char)'\0';
+ /* convert subr index to array index */
+ size_t* val = ft_hash_num_lookup( idx, type1->subrs_hash );
+
+
+ if ( val )
+ {
+ idx = *val;
+ ok = 1;
+ }
+ }
+ else
+ {
+ if ( idx < (FT_UInt)type1->num_subrs )
+ ok = 1;
+ }
+
+ if ( ok )
+ {
+ retval = type1->subrs_len[idx] + 1;
+ if ( value && value_len >= retval )
+ {
+ ft_memcpy( value, (void *)( type1->subrs[idx] ), retval - 1 );
+ ((FT_Char *)value)[retval - 1] = (FT_Char)'\0';
+ }
}
}
break;
--- a/src/type1/t1gload.c
+++ b/src/type1/t1gload.c
@@ -183,6 +183,7 @@
decoder.num_subrs = type1->num_subrs;
decoder.subrs = type1->subrs;
decoder.subrs_len = type1->subrs_len;
+ decoder.subrs_hash = type1->subrs_hash;
decoder.buildchar = face->buildchar;
decoder.len_buildchar = face->len_buildchar;
@@ -245,9 +246,10 @@
decoder.builder.metrics_only = 1;
decoder.builder.load_points = 0;
- decoder.num_subrs = type1->num_subrs;
- decoder.subrs = type1->subrs;
- decoder.subrs_len = type1->subrs_len;
+ decoder.num_subrs = type1->num_subrs;
+ decoder.subrs = type1->subrs;
+ decoder.subrs_len = type1->subrs_len;
+ decoder.subrs_hash = type1->subrs_hash;
decoder.buildchar = face->buildchar;
decoder.len_buildchar = face->len_buildchar;
@@ -346,6 +348,7 @@
decoder.num_subrs = type1->num_subrs;
decoder.subrs = type1->subrs;
decoder.subrs_len = type1->subrs_len;
+ decoder.subrs_hash = type1->subrs_hash;
decoder.buildchar = face->buildchar;
decoder.len_buildchar = face->len_buildchar;
--- a/src/type1/t1load.c
+++ b/src/type1/t1load.c
@@ -66,6 +66,7 @@
#include FT_MULTIPLE_MASTERS_H
#include FT_INTERNAL_TYPE1_TYPES_H
#include FT_INTERNAL_CALC_H
+#include FT_INTERNAL_HASH_H
#include "t1load.h"
#include "t1errors.h"
@@ -1404,6 +1405,8 @@
FT_Memory memory = parser->root.memory;
FT_Error error;
FT_Int num_subrs;
+ FT_Int count;
+ FT_Hash hash = NULL;
PSAux_Service psaux = (PSAux_Service)face->psaux;
@@ -1432,11 +1435,36 @@
/* we certainly need more than 8 bytes per subroutine */
if ( num_subrs > ( parser->root.limit - parser->root.cursor ) >> 3 )
{
+ /*
+ * There are two possibilities. Either the font contains an invalid
+ * value for `num_subrs', or we have a subsetted font where the
+ * subroutine indices are not adjusted, e.g.
+ *
+ * /Subrs 812 array
+ * dup 0 { ... } NP
+ * dup 51 { ... } NP
+ * dup 681 { ... } NP
+ * ND
+ *
+ * In both cases, we use a number hash that maps from subr indices to
+ * actual array elements.
+ */
+
FT_TRACE0(( "parse_subrs: adjusting number of subroutines"
" (from %d to %d)\n",
num_subrs,
( parser->root.limit - parser->root.cursor ) >> 3 ));
num_subrs = ( parser->root.limit - parser->root.cursor ) >> 3;
+
+ if ( !hash )
+ {
+ if ( FT_NEW( hash ) )
+ goto Fail;
+
+ error = ft_hash_init( hash, 1, memory );
+ if ( error )
+ goto Fail;
+ }
}
/* position the parser right before the `dup' of the first subr */
@@ -1458,7 +1486,7 @@
/* */
/* `index' + binary data */
/* */
- for (;;)
+ for ( count = 0; ; count++ )
{
FT_Long idx;
FT_ULong size;
@@ -1494,6 +1522,14 @@
T1_Skip_Spaces ( parser );
}
+ /* if we use a hash, the subrs index is the key, and a running */
+ /* counter specified for `T1_Add_Table' acts as the value */
+ if ( hash )
+ {
+ ft_hash_num_insert( idx, count, hash, memory );
+ idx = count;
+ }
+
/* with synthetic fonts it is possible we get here twice */
if ( loader->num_subrs )
continue;
@@ -1534,7 +1570,10 @@
}
if ( !loader->num_subrs )
- loader->num_subrs = num_subrs;
+ {
+ loader->num_subrs = num_subrs;
+ loader->subrs_hash = hash;
+ }
return;
@@ -2105,17 +2144,6 @@
FT_UNUSED( face );
FT_MEM_ZERO( loader, sizeof ( *loader ) );
- loader->num_glyphs = 0;
- loader->num_chars = 0;
-
- /* initialize the tables -- simply set their `init' field to 0 */
- loader->encoding_table.init = 0;
- loader->charstrings.init = 0;
- loader->glyph_names.init = 0;
- loader->subrs.init = 0;
- loader->swap_table.init = 0;
- loader->fontdata = 0;
- loader->keywords_encountered = 0;
}
@@ -2123,6 +2151,7 @@
t1_done_loader( T1_Loader loader )
{
T1_Parser parser = &loader->parser;
+ FT_Memory memory = parser->root.memory;
/* finalize tables */
@@ -2132,6 +2161,10 @@
T1_Release_Table( &loader->swap_table );
T1_Release_Table( &loader->subrs );
+ /* finalize hash */
+ ft_hash_free( loader->subrs_hash, memory );
+ FT_FREE( loader->subrs_hash );
+
/* finalize parser */
T1_Finalize_Parser( parser );
}
@@ -2248,11 +2281,15 @@
if ( loader.subrs.init )
{
- loader.subrs.init = 0;
type1->num_subrs = loader.num_subrs;
type1->subrs_block = loader.subrs.block;
type1->subrs = loader.subrs.elements;
type1->subrs_len = loader.subrs.lengths;
+ type1->subrs_hash = loader.subrs_hash;
+
+ /* prevent `t1_done_loader' from freeing the propagated data */
+ loader.subrs.init = 0;
+ loader.subrs_hash = NULL;
}
if ( !IS_INCREMENTAL )
--- a/src/type1/t1load.h
+++ b/src/type1/t1load.h
@@ -46,6 +46,7 @@
FT_Int num_subrs;
PS_TableRec subrs;
+ FT_Hash subrs_hash;
FT_Bool fontdata;
FT_UInt keywords_encountered; /* T1_LOADER_ENCOUNTERED_XXX */
--- a/src/type1/t1objs.c
+++ b/src/type1/t1objs.c
@@ -247,6 +247,9 @@
FT_FREE( type1->subrs );
FT_FREE( type1->subrs_len );
+ ft_hash_free( type1->subrs_hash, memory );
+ FT_FREE( type1->subrs_hash );
+
FT_FREE( type1->subrs_block );
FT_FREE( type1->charstrings_block );
FT_FREE( type1->glyph_names_block );