[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.
This commit is contained in:
Werner Lemberg 2015-12-20 19:36:04 +01:00
parent 1caf629eef
commit bd4b8976a3
10 changed files with 147 additions and 25 deletions

View File

@ -1,3 +1,38 @@
2015-12-20 Werner Lemberg <wl@gnu.org>
[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 <wl@gnu.org>
[base] Thinko: Remove free function pointer.

View File

@ -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_BEGIN_HEADER
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;

View File

@ -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_BEGIN_HEADER
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 */

View File

@ -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;

View File

@ -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:"

View File

@ -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;

View File

@ -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;

View File

@ -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 )

View File

@ -46,6 +46,7 @@ FT_BEGIN_HEADER
FT_Int num_subrs;
PS_TableRec subrs;
FT_Hash subrs_hash;
FT_Bool fontdata;
FT_UInt keywords_encountered; /* T1_LOADER_ENCOUNTERED_XXX */

View File

@ -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 );