[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:
parent
1caf629eef
commit
bd4b8976a3
35
ChangeLog
35
ChangeLog
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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:"
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 )
|
||||
|
@ -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 */
|
||||
|
@ -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 );
|
||||
|
Loading…
x
Reference in New Issue
Block a user