diff options
Diffstat (limited to 'third_party/freetype/src/truetype/ttpload.c')
-rw-r--r-- | third_party/freetype/src/truetype/ttpload.c | 81 |
1 files changed, 57 insertions, 24 deletions
diff --git a/third_party/freetype/src/truetype/ttpload.c b/third_party/freetype/src/truetype/ttpload.c index 4647c938ae..70ac15da4a 100644 --- a/third_party/freetype/src/truetype/ttpload.c +++ b/third_party/freetype/src/truetype/ttpload.c @@ -4,7 +4,7 @@ /* */ /* TrueType-specific tables loader (body). */ /* */ -/* Copyright 1996-2015 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -73,9 +73,21 @@ /* it is possible that a font doesn't have a glyf table at all */ /* or its size is zero */ if ( FT_ERR_EQ( error, Table_Missing ) ) - face->glyf_len = 0; + { + face->glyf_len = 0; + face->glyf_offset = 0; + } else if ( error ) goto Exit; + else + { +#ifdef FT_CONFIG_OPTION_INCREMENTAL + if ( face->root.internal->incremental_interface ) + face->glyf_offset = 0; + else +#endif + face->glyf_offset = FT_STREAM_POS(); + } FT_TRACE2(( "Locations " )); error = face->goto_table( face, TTAG_loca, stream, &table_len ); @@ -92,8 +104,7 @@ if ( table_len >= 0x40000L ) { FT_TRACE2(( "table too large\n" )); - error = FT_THROW( Invalid_Table ); - goto Exit; + table_len = 0x3FFFFL; } face->num_locations = table_len >> shift; } @@ -104,8 +115,7 @@ if ( table_len >= 0x20000L ) { FT_TRACE2(( "table too large\n" )); - error = FT_THROW( Invalid_Table ); - goto Exit; + table_len = 0x1FFFFL; } face->num_locations = table_len >> shift; } @@ -124,8 +134,9 @@ TT_Table entry = face->dir_tables; TT_Table limit = entry + face->num_tables; - FT_Long pos = (FT_Long)FT_STREAM_POS(); - FT_Long dist = 0x7FFFFFFFL; + FT_Long pos = (FT_Long)FT_STREAM_POS(); + FT_Long dist = 0x7FFFFFFFL; + FT_Bool found = 0; /* compute the distance to next table in font file */ @@ -135,10 +146,13 @@ if ( diff > 0 && diff < dist ) - dist = diff; + { + dist = diff; + found = 1; + } } - if ( entry == limit ) + if ( !found ) { /* `loca' is the last table */ dist = (FT_Long)stream->size - pos; @@ -218,12 +232,13 @@ } } - /* Check broken location data */ + /* Check broken location data. */ if ( pos1 > face->glyf_len ) { FT_TRACE1(( "tt_face_get_location:" - " too large offset=0x%08lx found for gid=0x%04lx," - " exceeding the end of glyf table (0x%08lx)\n", + " too large offset (0x%08lx) found for glyph index %ld,\n" + " " + " exceeding the end of `glyf' table (0x%08lx)\n", pos1, gindex, face->glyf_len )); *asize = 0; return 0; @@ -231,11 +246,26 @@ if ( pos2 > face->glyf_len ) { - FT_TRACE1(( "tt_face_get_location:" - " too large offset=0x%08lx found for gid=0x%04lx," - " truncate at the end of glyf table (0x%08lx)\n", - pos2, gindex + 1, face->glyf_len )); - pos2 = face->glyf_len; + /* We try to sanitize the last `loca' entry. */ + if ( gindex == face->num_locations - 1 ) + { + FT_TRACE1(( "tt_face_get_location:" + " too large offset (0x%08lx) found for glyph index %ld,\n" + " " + " truncating at the end of `glyf' table (0x%08lx)\n", + pos2, gindex + 1, face->glyf_len )); + pos2 = face->glyf_len; + } + else + { + FT_TRACE1(( "tt_face_get_location:" + " too large offset (0x%08lx) found for glyph index %ld,\n" + " " + " exceeding the end of `glyf' table (0x%08lx)\n", + pos2, gindex + 1, face->glyf_len )); + *asize = 0; + return 0; + } } /* The `loca' table must be ordered; it refers to the length of */ @@ -494,7 +524,7 @@ { FT_Error error; FT_Memory memory = stream->memory; - FT_UInt version, nn, num_records; + FT_UInt nn, num_records; FT_ULong table_size, record_size; FT_Byte* p; FT_Byte* limit; @@ -511,7 +541,10 @@ p = face->hdmx_table; limit = p + table_size; - version = FT_NEXT_USHORT( p ); + /* Given that `hdmx' tables are losing its importance (for example, */ + /* variation fonts introduced in OpenType 1.8 must not have this */ + /* table) we no longer test for a correct `version' field. */ + p += 2; num_records = FT_NEXT_USHORT( p ); record_size = FT_NEXT_ULONG( p ); @@ -530,10 +563,10 @@ record_size &= 0xFFFFU; /* The limit for `num_records' is a heuristic value. */ - if ( version != 0 || - num_records > 255 || - record_size > 0x10001L || - record_size < 4 ) + if ( num_records > 255 || + ( num_records > 0 && + ( record_size > 0x10001L || + record_size < 4 ) ) ) { error = FT_THROW( Invalid_File_Format ); goto Fail; |