diff options
author | David Turner <david@freetype.org> | 2002-07-11 23:41:14 +0000 |
---|---|---|
committer | David Turner <david@freetype.org> | 2002-07-11 23:41:14 +0000 |
commit | 7acd73fd6a6f34a2d40dfcbe47d18f5b5cb81888 (patch) | |
tree | 2d3b35f6969fe44eb051d2c8b31dde72154d7318 /src | |
parent | 660138753b036ea5fe14c55c1ee2a57ea7615431 (diff) | |
download | freetype2-7acd73fd6a6f34a2d40dfcbe47d18f5b5cb81888.tar.gz |
* src/sfnt/ttload.c, src/sfnt/ttload.h, src/sfnt/ttdriver.c: changing
the SFNT loader to check for SFNT-based font files differently. We now
ignore the range "helper" fields and check the "head" table's magic
number instead.
Diffstat (limited to 'src')
-rw-r--r-- | src/base/fthash.c | 2 | ||||
-rw-r--r-- | src/base/ftobject.c | 1 | ||||
-rw-r--r-- | src/sfnt/sfdriver.c | 2 | ||||
-rw-r--r-- | src/sfnt/ttload.c | 134 | ||||
-rw-r--r-- | src/sfnt/ttload.h | 8 |
5 files changed, 115 insertions, 32 deletions
diff --git a/src/base/fthash.c b/src/base/fthash.c index 036922452..c42b1dcf4 100644 --- a/src/base/fthash.c +++ b/src/base/fthash.c @@ -197,7 +197,7 @@ num_buckets = ( table->p + table->mask + 1) ; - if ( ++ table->slack > num_buckets*FT_HASH_SUB_LOAD ) + if ( ++ table->slack > (FT_Long)num_buckets*FT_HASH_SUB_LOAD ) { FT_UInt p = table->p; FT_UInt mask = table->mask; diff --git a/src/base/ftobject.c b/src/base/ftobject.c index f51e6c031..413384c8d 100644 --- a/src/base/ftobject.c +++ b/src/base/ftobject.c @@ -312,6 +312,7 @@ return (clazz == NULL); } + return 0; } diff --git a/src/sfnt/sfdriver.c b/src/sfnt/sfdriver.c index f0316e293..6411d9165 100644 --- a/src/sfnt/sfdriver.c +++ b/src/sfnt/sfdriver.c @@ -251,7 +251,7 @@ SFNT_Get_Interface, TT_Load_Any, - TT_Load_SFNT_HeaderRec, + TT_Load_SFNT_Header, TT_Load_Directory, TT_Load_Header, diff --git a/src/sfnt/ttload.c b/src/sfnt/ttload.c index e3dada296..4c0595859 100644 --- a/src/sfnt/ttload.c +++ b/src/sfnt/ttload.c @@ -135,6 +135,91 @@ } + /* in theory, we should check the values of `search_range', */ + /* `entry_selector' and `range_shift' to detect non-SFNT based files */ + /* whose header might also start with 0x100000L (yes, these exist). */ + /* */ + /* Very unfortunately, many TrueType fonts don't have these fields */ + /* set correctly and we must ignore them to support them. An alternative */ + /* way to check the font file is thus to: */ + /* */ + /* - check that `num_tables' is valid */ + /* - look for a "head" table, check its size, and parse it to */ + /* see if its "magic" field is correctly set to */ + /* */ + /* Voila, here comes robust though tolerant font format checking :-) */ + /* */ + static FT_Error + sfnt_dir_check( FT_Stream stream, + FT_ULong offset, + FT_UInt num_tables ) + { + FT_Error error; + FT_UInt nn; + + static const FT_Frame_Field sfnt_dir_entry_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE TT_TableRec + + FT_FRAME_START( 16 ), + FT_FRAME_ULONG( Tag ), + FT_FRAME_ULONG( CheckSum ), + FT_FRAME_ULONG( Offset ), + FT_FRAME_ULONG( Length ), + FT_FRAME_END + }; + + /* if 'num_tables' is 0, read the table count from the file */ + if ( num_tables == 0 ) + { + FT_ULong format_tag; + + if ( FT_STREAM_SEEK( offset ) || + FT_READ_ULONG ( format_tag ) || + FT_READ_USHORT( num_tables ) || + FT_STREAM_SKIP( 6 ) ) + goto Bad_Format; + + if ( offset + 12 + num_tables*16 > stream->size ) + goto Bad_Format; + } + else if ( FT_STREAM_SEEK( offset + 12 ) ) + goto Bad_Format; + + for ( nn = 0; nn < num_tables; nn++ ) + { + TT_TableRec table; + + if ( FT_STREAM_READ_FIELDS( sfnt_dir_entry_fields, &table ) ) + goto Bad_Format; + + if ( offset + table.Offset + table.Length > stream->size ) + goto Bad_Format; + + if ( table.Tag == TTAG_head ) + { + FT_UInt32 magic; + + if ( table.Length != 0x36 || + FT_STREAM_SEEK( offset + table.Offset + 12 ) || + FT_READ_ULONG( magic ) || + magic != 0x5F0F3CF5U ) + goto Bad_Format; + + if ( FT_STREAM_SEEK( offset + 28 + 16*nn ) ) + goto Bad_Format; + } + } + + Exit: + return error; + + Bad_Format: + error = FT_Err_Unknown_File_Format; + goto Exit; + } + /*************************************************************************/ /* */ /* <Function> */ @@ -166,16 +251,16 @@ /* values of `search_range', `entry_selector', and `range_shift'. */ /* */ FT_LOCAL_DEF( FT_Error ) - TT_Load_SFNT_HeaderRec( TT_Face face, - FT_Stream stream, - FT_Long face_index, - SFNT_Header sfnt ) + TT_Load_SFNT_Header( TT_Face face, + FT_Stream stream, + FT_Long face_index, + SFNT_Header sfnt ) { FT_Error error; - FT_ULong format_tag; + FT_ULong format_tag, offset; FT_Memory memory = stream->memory; - const FT_Frame_Field sfnt_header_fields[] = + static const FT_Frame_Field sfnt_header_fields[] = { #undef FT_STRUCTURE #define FT_STRUCTURE SFNT_HeaderRec @@ -188,7 +273,7 @@ FT_FRAME_END }; - const FT_Frame_Field ttc_header_fields[] = + static const FT_Frame_Field ttc_header_fields[] = { #undef FT_STRUCTURE #define FT_STRUCTURE TTC_HeaderRec @@ -200,7 +285,7 @@ }; - FT_TRACE2(( "TT_Load_SFNT_HeaderRec: %08p, %ld\n", + FT_TRACE2(( "TT_Load_SFNT_Header: %08p, %ld\n", face, face_index )); face->ttc_header.tag = 0; @@ -213,6 +298,8 @@ /* file is a TrueType collection, otherwise it can be any other */ /* kind of font. */ /* */ + offset = FT_STREAM_POS(); + if ( FT_READ_ULONG( format_tag ) ) goto Exit; @@ -221,7 +308,7 @@ FT_Int n; - FT_TRACE3(( "TT_Load_SFNT_HeaderRec: file is a collection\n" )); + FT_TRACE3(( "TT_Load_SFNT_Header: file is a collection\n" )); /* It is a TrueType collection, i.e. a file containing several */ /* font files. Read the font directory now */ @@ -246,32 +333,26 @@ } /* seek to the appropriate TrueType file, then read tag */ - if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) || + offset = face->ttc_header.offsets[ face_index ]; + + if ( FT_STREAM_SEEK( offset ) || FT_READ_LONG( format_tag ) ) goto Exit; } /* the format tag was read, now check the rest of the header */ sfnt->format_tag = format_tag; + sfnt->offset = offset; + if ( FT_STREAM_READ_FIELDS( sfnt_header_fields, sfnt ) ) goto Exit; - /* now, check the values of `num_tables', `seach_range', etc. */ + /* now check the sfnt directory */ + error = sfnt_dir_check( stream, offset, sfnt->num_tables ); + if ( error ) { - FT_UInt num_tables = sfnt->num_tables; - FT_ULong entry_selector = 1L << sfnt->entry_selector; - - - /* IMPORTANT: Many fonts have an incorrect `search_range' value, so */ - /* we only check the `entry_selector' correctness here. */ - /* */ - if ( num_tables == 0 || - entry_selector > num_tables || - entry_selector * 2 <= num_tables ) - { - FT_TRACE2(( "TT_Load_SFNT_HeaderRec: file is not SFNT!\n" )); - error = SFNT_Err_Unknown_File_Format; - } + FT_TRACE2(( "TT_Load_SFNT_Header: file is not SFNT!\n" )); + error = SFNT_Err_Unknown_File_Format; } Exit: @@ -322,7 +403,8 @@ if ( FT_NEW_ARRAY( face->dir_tables, face->num_tables ) ) goto Exit; - if ( FT_FRAME_ENTER( face->num_tables * 16L ) ) + if ( FT_STREAM_SEEK( sfnt->offset + 12 ) || + FT_FRAME_ENTER( face->num_tables * 16L ) ) goto Exit; entry = face->dir_tables; diff --git a/src/sfnt/ttload.h b/src/sfnt/ttload.h index 67ec052fd..f7981dd9f 100644 --- a/src/sfnt/ttload.h +++ b/src/sfnt/ttload.h @@ -41,10 +41,10 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) - TT_Load_SFNT_HeaderRec( TT_Face face, - FT_Stream stream, - FT_Long face_index, - SFNT_Header sfnt ); + TT_Load_SFNT_Header( TT_Face face, + FT_Stream stream, + FT_Long face_index, + SFNT_Header sfnt ); FT_LOCAL( FT_Error ) TT_Load_Directory( TT_Face face, |