Index: third_party/freetype/src/type1/t1load.c |
diff --git a/third_party/freetype/src/type1/t1load.c b/third_party/freetype/src/type1/t1load.c |
index 22b3f6b31ddc40587c7952484d08678c6317454a..dbf4eafd716a31760b7273b9e2f9606cbebab261 100644 |
--- a/third_party/freetype/src/type1/t1load.c |
+++ b/third_party/freetype/src/type1/t1load.c |
@@ -4,7 +4,7 @@ |
/* */ |
/* Type 1 font loader (body). */ |
/* */ |
-/* Copyright 1996-2014 by */ |
+/* Copyright 1996-2015 by */ |
/* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
/* */ |
/* This file is part of the FreeType project, and may only be used, */ |
@@ -226,7 +226,7 @@ |
/* Given a normalized (blend) coordinate, figure out the design */ |
/* coordinate appropriate for that value. */ |
/* */ |
- FT_LOCAL_DEF( FT_Fixed ) |
+ static FT_Fixed |
mm_axis_unmap( PS_DesignMap axismap, |
FT_Fixed ncv ) |
{ |
@@ -255,7 +255,7 @@ |
/* Given a vector of weights, one for each design, figure out the */ |
/* normalized axis coordinates which gave rise to those weights. */ |
/* */ |
- FT_LOCAL_DEF( void ) |
+ static void |
mm_weights_unmap( FT_Fixed* weights, |
FT_Fixed* axiscoords, |
FT_UInt axis_count ) |
@@ -368,44 +368,43 @@ |
FT_Fixed* coords ) |
{ |
PS_Blend blend = face->blend; |
- FT_Error error; |
FT_UInt n, m; |
- error = FT_ERR( Invalid_Argument ); |
+ if ( !blend ) |
+ return FT_THROW( Invalid_Argument ); |
+ |
+ if ( num_coords > blend->num_axis ) |
+ num_coords = blend->num_axis; |
- if ( blend && blend->num_axis == num_coords ) |
+ /* recompute the weight vector from the blend coordinates */ |
+ for ( n = 0; n < blend->num_designs; n++ ) |
{ |
- /* recompute the weight vector from the blend coordinates */ |
- for ( n = 0; n < blend->num_designs; n++ ) |
- { |
- FT_Fixed result = 0x10000L; /* 1.0 fixed */ |
+ FT_Fixed result = 0x10000L; /* 1.0 fixed */ |
- for ( m = 0; m < blend->num_axis; m++ ) |
- { |
- FT_Fixed factor; |
+ for ( m = 0; m < blend->num_axis; m++ ) |
+ { |
+ FT_Fixed factor; |
- /* get current blend axis position */ |
- factor = coords[m]; |
- if ( factor < 0 ) |
- factor = 0; |
- if ( factor > 0x10000L ) |
- factor = 0x10000L; |
+ /* get current blend axis position; */ |
+ /* use a default value if we don't have a coordinate */ |
+ factor = m < num_coords ? coords[m] : 0x8000; |
+ if ( factor < 0 ) |
+ factor = 0; |
+ if ( factor > 0x10000L ) |
+ factor = 0x10000L; |
- if ( ( n & ( 1 << m ) ) == 0 ) |
- factor = 0x10000L - factor; |
+ if ( ( n & ( 1 << m ) ) == 0 ) |
+ factor = 0x10000L - factor; |
- result = FT_MulFix( result, factor ); |
- } |
- blend->weight_vector[n] = result; |
+ result = FT_MulFix( result, factor ); |
} |
- |
- error = FT_Err_Ok; |
+ blend->weight_vector[n] = result; |
} |
- return error; |
+ return FT_Err_Ok; |
} |
@@ -415,68 +414,72 @@ |
FT_Long* coords ) |
{ |
PS_Blend blend = face->blend; |
- FT_Error error; |
FT_UInt n, p; |
+ FT_Fixed final_blends[T1_MAX_MM_DESIGNS]; |
- error = FT_ERR( Invalid_Argument ); |
- if ( blend && blend->num_axis == num_coords ) |
- { |
- /* compute the blend coordinates through the blend design map */ |
- FT_Fixed final_blends[T1_MAX_MM_DESIGNS]; |
+ if ( !blend ) |
+ return FT_THROW( Invalid_Argument ); |
+ if ( num_coords > blend->num_axis ) |
+ num_coords = blend->num_axis; |
- for ( n = 0; n < blend->num_axis; n++ ) |
- { |
- FT_Long design = coords[n]; |
- FT_Fixed the_blend; |
- PS_DesignMap map = blend->design_map + n; |
- FT_Long* designs = map->design_points; |
- FT_Fixed* blends = map->blend_points; |
- FT_Int before = -1, after = -1; |
+ /* compute the blend coordinates through the blend design map */ |
+ for ( n = 0; n < blend->num_axis; n++ ) |
+ { |
+ FT_Long design; |
+ FT_Fixed the_blend; |
+ PS_DesignMap map = blend->design_map + n; |
+ FT_Long* designs = map->design_points; |
+ FT_Fixed* blends = map->blend_points; |
+ FT_Int before = -1, after = -1; |
- for ( p = 0; p < (FT_UInt)map->num_points; p++ ) |
- { |
- FT_Long p_design = designs[p]; |
+ /* use a default value if we don't have a coordinate */ |
+ if ( n < num_coords ) |
+ design = coords[n]; |
+ else |
+ design = ( designs[map->num_points - 1] - designs[0] ) / 2; |
- /* exact match? */ |
- if ( design == p_design ) |
- { |
- the_blend = blends[p]; |
- goto Found; |
- } |
+ for ( p = 0; p < (FT_UInt)map->num_points; p++ ) |
+ { |
+ FT_Long p_design = designs[p]; |
- if ( design < p_design ) |
- { |
- after = p; |
- break; |
- } |
- before = p; |
+ /* exact match? */ |
+ if ( design == p_design ) |
+ { |
+ the_blend = blends[p]; |
+ goto Found; |
} |
- /* now interpolate if necessary */ |
- if ( before < 0 ) |
- the_blend = blends[0]; |
+ if ( design < p_design ) |
+ { |
+ after = (FT_Int)p; |
+ break; |
+ } |
- else if ( after < 0 ) |
- the_blend = blends[map->num_points - 1]; |
+ before = (FT_Int)p; |
+ } |
- else |
- the_blend = FT_MulDiv( design - designs[before], |
- blends [after] - blends [before], |
- designs[after] - designs[before] ); |
+ /* now interpolate if necessary */ |
+ if ( before < 0 ) |
+ the_blend = blends[0]; |
- Found: |
- final_blends[n] = the_blend; |
- } |
+ else if ( after < 0 ) |
+ the_blend = blends[map->num_points - 1]; |
- error = T1_Set_MM_Blend( face, num_coords, final_blends ); |
+ else |
+ the_blend = FT_MulDiv( design - designs[before], |
+ blends [after] - blends [before], |
+ designs[after] - designs[before] ); |
+ |
+ Found: |
+ final_blends[n] = the_blend; |
} |
- return error; |
+ return T1_Set_MM_Blend( face, blend->num_axis, final_blends ); |
} |
@@ -490,20 +493,17 @@ |
FT_UInt num_coords, |
FT_Fixed* coords ) |
{ |
- FT_Long lcoords[4]; /* maximum axis count is 4 */ |
- FT_UInt i; |
- FT_Error error; |
+ FT_Long lcoords[T1_MAX_MM_AXIS]; |
+ FT_UInt i; |
+ |
+ if ( num_coords > T1_MAX_MM_AXIS ) |
+ num_coords = T1_MAX_MM_AXIS; |
- error = FT_ERR( Invalid_Argument ); |
- if ( num_coords <= 4 && num_coords > 0 ) |
- { |
- for ( i = 0; i < num_coords; ++i ) |
- lcoords[i] = FIXED_TO_INT( coords[i] ); |
- error = T1_Set_MM_Design( face, num_coords, lcoords ); |
- } |
+ for ( i = 0; i < num_coords; ++i ) |
+ lcoords[i] = FIXED_TO_INT( coords[i] ); |
- return error; |
+ return T1_Set_MM_Design( face, num_coords, lcoords ); |
} |
@@ -599,23 +599,32 @@ |
/* each token is an immediate containing the name of the axis */ |
for ( n = 0; n < num_axis; n++ ) |
{ |
- T1_Token token = axis_tokens + n; |
- FT_Byte* name; |
- FT_PtrDist len; |
+ T1_Token token = axis_tokens + n; |
+ FT_Byte* name; |
+ FT_UInt len; |
/* skip first slash, if any */ |
if ( token->start[0] == '/' ) |
token->start++; |
- len = token->limit - token->start; |
+ len = (FT_UInt)( token->limit - token->start ); |
if ( len == 0 ) |
{ |
error = FT_THROW( Invalid_File_Format ); |
goto Exit; |
} |
- if ( FT_ALLOC( blend->axis_names[n], (FT_Long)( len + 1 ) ) ) |
+ name = (FT_Byte*)blend->axis_names[n]; |
+ if ( name ) |
+ { |
+ FT_TRACE0(( "parse_blend_axis_types:" |
+ " overwriting axis name `%s' with `%*.s'\n", |
+ name, len, token->start )); |
+ FT_FREE( name ); |
+ } |
+ |
+ if ( FT_ALLOC( blend->axis_names[n], len + 1 ) ) |
goto Exit; |
name = (FT_Byte*)blend->axis_names[n]; |
@@ -692,7 +701,9 @@ |
} |
num_axis = n_axis; |
- error = t1_allocate_blend( face, num_designs, num_axis ); |
+ error = t1_allocate_blend( face, |
+ (FT_UInt)num_designs, |
+ (FT_UInt)num_axis ); |
if ( error ) |
goto Exit; |
blend = face->blend; |
@@ -757,7 +768,7 @@ |
old_cursor = parser->root.cursor; |
old_limit = parser->root.limit; |
- error = t1_allocate_blend( face, 0, num_axis ); |
+ error = t1_allocate_blend( face, 0, (FT_UInt)num_axis ); |
if ( error ) |
goto Exit; |
blend = face->blend; |
@@ -785,6 +796,13 @@ |
goto Exit; |
} |
+ if ( map->design_points ) |
+ { |
+ FT_ERROR(( "parse_blend_design_map: duplicate table\n" )); |
+ error = FT_THROW( Invalid_File_Format ); |
+ goto Exit; |
+ } |
+ |
/* allocate design map data */ |
if ( FT_NEW_ARRAY( map->design_points, num_points * 2 ) ) |
goto Exit; |
@@ -848,7 +866,7 @@ |
if ( !blend || !blend->num_designs ) |
{ |
- error = t1_allocate_blend( face, num_designs, 0 ); |
+ error = t1_allocate_blend( face, (FT_UInt)num_designs, 0 ); |
if ( error ) |
goto Exit; |
blend = face->blend; |
@@ -890,8 +908,8 @@ |
parse_buildchar( T1_Face face, |
T1_Loader loader ) |
{ |
- face->len_buildchar = T1_ToFixedArray( &loader->parser, 0, NULL, 0 ); |
- |
+ face->len_buildchar = (FT_UInt)T1_ToFixedArray( &loader->parser, |
+ 0, NULL, 0 ); |
return; |
} |
@@ -1038,9 +1056,11 @@ |
} |
+ /* return 1 in case of success */ |
+ |
static int |
read_binary_data( T1_Parser parser, |
- FT_Long* size, |
+ FT_ULong* size, |
FT_Byte** base, |
FT_Bool incremental ) |
{ |
@@ -1072,7 +1092,7 @@ |
if ( s >= 0 && s < limit - *base ) |
{ |
parser->root.cursor += s + 1; |
- *size = s; |
+ *size = (FT_ULong)s; |
return !parser->root.error; |
} |
} |
@@ -1103,6 +1123,7 @@ |
FT_Int result; |
+ /* input is scaled by 1000 to accommodate default FontMatrix */ |
result = T1_ToFixedArray( parser, 6, temp, 3 ); |
if ( result < 6 ) |
@@ -1120,15 +1141,12 @@ |
return; |
} |
- /* Set Units per EM based on FontMatrix values. We set the value to */ |
- /* 1000 / temp_scale, because temp_scale was already multiplied by */ |
- /* 1000 (in t1_tofixed, from psobjs.c). */ |
- |
- root->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale ); |
- |
- /* we need to scale the values by 1.0/temp_scale */ |
+ /* atypical case */ |
if ( temp_scale != 0x10000L ) |
{ |
+ /* set units per EM based on FontMatrix values */ |
+ root->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale ); |
+ |
temp[0] = FT_DivFix( temp[0], temp_scale ); |
temp[1] = FT_DivFix( temp[1], temp_scale ); |
temp[2] = FT_DivFix( temp[2], temp_scale ); |
@@ -1190,10 +1208,27 @@ |
else |
count = (FT_Int)T1_ToInt( parser ); |
+ /* only composite fonts (which we don't support) */ |
+ /* can have larger values */ |
+ if ( count > 256 ) |
+ { |
+ FT_ERROR(( "parse_encoding: invalid encoding array size\n" )); |
+ parser->root.error = FT_THROW( Invalid_File_Format ); |
+ return; |
+ } |
+ |
T1_Skip_Spaces( parser ); |
if ( parser->root.cursor >= limit ) |
return; |
+ /* PostScript happily allows overwriting of encoding arrays */ |
+ if ( encode->char_index ) |
+ { |
+ FT_FREE( encode->char_index ); |
+ FT_FREE( encode->char_name ); |
+ T1_Release_Table( char_table ); |
+ } |
+ |
/* we use a T1_Table to store our charnames */ |
loader->num_chars = encode->num_chars = count; |
if ( FT_NEW_ARRAY( encode->char_index, count ) || |
@@ -1285,7 +1320,7 @@ |
if ( cur + 2 < limit && *cur == '/' && n < count ) |
{ |
- FT_PtrDist len; |
+ FT_UInt len; |
cur++; |
@@ -1297,7 +1332,7 @@ |
if ( parser->root.error ) |
return; |
- len = parser->root.cursor - cur; |
+ len = (FT_UInt)( parser->root.cursor - cur ); |
parser->root.error = T1_Add_Table( char_table, charcode, |
cur, len + 1 ); |
@@ -1407,7 +1442,8 @@ |
/* */ |
for (;;) |
{ |
- FT_Long idx, size; |
+ FT_Long idx; |
+ FT_ULong size; |
FT_Byte* base; |
@@ -1457,7 +1493,7 @@ |
/* some fonts define empty subr records -- this is not totally */ |
/* compliant to the specification (which says they should at */ |
/* least contain a `return'), but we support them anyway */ |
- if ( size < face->type1.private_dict.lenIV ) |
+ if ( size < (FT_ULong)face->type1.private_dict.lenIV ) |
{ |
error = FT_THROW( Invalid_File_Format ); |
goto Fail; |
@@ -1468,7 +1504,7 @@ |
goto Fail; |
FT_MEM_COPY( temp, base, size ); |
psaux->t1_decrypt( temp, size, 4330 ); |
- size -= face->type1.private_dict.lenIV; |
+ size -= (FT_ULong)face->type1.private_dict.lenIV; |
error = T1_Add_Table( table, (FT_Int)idx, |
temp + face->type1.private_dict.lenIV, size ); |
FT_FREE( temp ); |
@@ -1505,10 +1541,10 @@ |
PSAux_Service psaux = (PSAux_Service)face->psaux; |
- FT_Byte* cur; |
+ FT_Byte* cur = parser->root.cursor; |
FT_Byte* limit = parser->root.limit; |
FT_Int n, num_glyphs; |
- FT_UInt notdef_index = 0; |
+ FT_Int notdef_index = 0; |
FT_Byte notdef_found = 0; |
@@ -1519,6 +1555,15 @@ |
goto Fail; |
} |
+ /* we certainly need more than 8 bytes per glyph */ |
+ if ( num_glyphs > ( limit - cur ) >> 3 ) |
+ { |
+ FT_TRACE0(( "parse_charstrings: adjusting number of glyphs" |
+ " (from %d to %d)\n", |
+ num_glyphs, ( limit - cur ) >> 3 )); |
+ num_glyphs = ( limit - cur ) >> 3; |
+ } |
+ |
/* some fonts like Optima-Oblique not only define the /CharStrings */ |
/* array but access it also */ |
if ( num_glyphs == 0 || parser->root.error ) |
@@ -1555,7 +1600,7 @@ |
for (;;) |
{ |
- FT_Long size; |
+ FT_ULong size; |
FT_Byte* base; |
@@ -1606,7 +1651,7 @@ |
if ( *cur == '/' ) |
{ |
- FT_PtrDist len; |
+ FT_UInt len; |
if ( cur + 2 >= limit ) |
@@ -1616,7 +1661,7 @@ |
} |
cur++; /* skip `/' */ |
- len = parser->root.cursor - cur; |
+ len = (FT_UInt)( parser->root.cursor - cur ); |
if ( !read_binary_data( parser, &size, &base, IS_INCREMENTAL ) ) |
return; |
@@ -1649,7 +1694,7 @@ |
FT_Byte* temp; |
- if ( size <= face->type1.private_dict.lenIV ) |
+ if ( size <= (FT_ULong)face->type1.private_dict.lenIV ) |
{ |
error = FT_THROW( Invalid_File_Format ); |
goto Fail; |
@@ -1660,7 +1705,7 @@ |
goto Fail; |
FT_MEM_COPY( temp, base, size ); |
psaux->t1_decrypt( temp, size, 4330 ); |
- size -= face->type1.private_dict.lenIV; |
+ size -= (FT_ULong)face->type1.private_dict.lenIV; |
error = T1_Add_Table( code_table, n, |
temp + face->type1.private_dict.lenIV, size ); |
FT_FREE( temp ); |
@@ -1838,15 +1883,11 @@ |
}; |
-#define T1_FIELD_COUNT \ |
- ( sizeof ( t1_keywords ) / sizeof ( t1_keywords[0] ) ) |
- |
- |
static FT_Error |
parse_dict( T1_Face face, |
T1_Loader loader, |
FT_Byte* base, |
- FT_Long size ) |
+ FT_ULong size ) |
{ |
T1_Parser parser = &loader->parser; |
FT_Byte *limit, *start_binary = NULL; |
@@ -1902,7 +1943,7 @@ |
else if ( *cur == 'R' && cur + 6 < limit && *(cur + 1) == 'D' && |
have_integer ) |
{ |
- FT_Long s; |
+ FT_ULong s; |
FT_Byte* b; |
@@ -1915,7 +1956,7 @@ |
else if ( *cur == '-' && cur + 6 < limit && *(cur + 1) == '|' && |
have_integer ) |
{ |
- FT_Long s; |
+ FT_ULong s; |
FT_Byte* b; |
@@ -1928,7 +1969,7 @@ |
/* look for immediates */ |
else if ( *cur == '/' && cur + 2 < limit ) |
{ |
- FT_PtrDist len; |
+ FT_UInt len; |
cur++; |
@@ -1938,7 +1979,7 @@ |
if ( parser->root.error ) |
goto Exit; |
- len = parser->root.cursor - cur; |
+ len = (FT_UInt)( parser->root.cursor - cur ); |
if ( len > 0 && len < 22 && parser->root.cursor < limit ) |
{ |
@@ -1955,9 +1996,9 @@ |
if ( !name ) |
break; |
- if ( cur[0] == name[0] && |
- len == (FT_PtrDist)ft_strlen( (const char *)name ) && |
- ft_memcmp( cur, name, len ) == 0 ) |
+ if ( cur[0] == name[0] && |
+ len == ft_strlen( (const char *)name ) && |
+ ft_memcmp( cur, name, len ) == 0 ) |
{ |
/* We found it -- run the parsing callback! */ |
/* We record every instance of every field */ |
@@ -2212,8 +2253,8 @@ |
/* the `lengths' field must be released later */ |
type1->glyph_names_block = loader.glyph_names.block; |
type1->glyph_names = (FT_String**)loader.glyph_names.elements; |
- loader.glyph_names.block = 0; |
- loader.glyph_names.elements = 0; |
+ loader.glyph_names.block = NULL; |
+ loader.glyph_names.elements = NULL; |
/* we must now build type1.encoding when we have a custom array */ |
if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY ) |