summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/freetype/src/truetype/ttpload.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/freetype/src/truetype/ttpload.c')
-rw-r--r--src/3rdparty/freetype/src/truetype/ttpload.c83
1 files changed, 56 insertions, 27 deletions
diff --git a/src/3rdparty/freetype/src/truetype/ttpload.c b/src/3rdparty/freetype/src/truetype/ttpload.c
index ecdd7376e1..9991925425 100644
--- a/src/3rdparty/freetype/src/truetype/ttpload.c
+++ b/src/3rdparty/freetype/src/truetype/ttpload.c
@@ -4,7 +4,7 @@
/* */
/* TrueType-specific tables loader (body). */
/* */
-/* Copyright 1996-2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009 by */
+/* Copyright 1996-2002, 2004-2013 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -72,7 +72,7 @@
/* it is possible that a font doesn't have a glyf table at all */
/* or its size is zero */
- if ( error == TT_Err_Table_Missing )
+ if ( FT_ERR_EQ( error, Table_Missing ) )
face->glyf_len = 0;
else if ( error )
goto Exit;
@@ -81,7 +81,7 @@
error = face->goto_table( face, TTAG_loca, stream, &table_len );
if ( error )
{
- error = TT_Err_Locations_Missing;
+ error = FT_THROW( Locations_Missing );
goto Exit;
}
@@ -92,7 +92,7 @@
if ( table_len >= 0x40000L )
{
FT_TRACE2(( "table too large\n" ));
- error = TT_Err_Invalid_Table;
+ error = FT_THROW( Invalid_Table );
goto Exit;
}
face->num_locations = table_len >> shift;
@@ -104,21 +104,22 @@
if ( table_len >= 0x20000L )
{
FT_TRACE2(( "table too large\n" ));
- error = TT_Err_Invalid_Table;
+ error = FT_THROW( Invalid_Table );
goto Exit;
}
face->num_locations = table_len >> shift;
}
- if ( face->num_locations != (FT_ULong)face->root.num_glyphs )
+ if ( face->num_locations != (FT_ULong)face->root.num_glyphs + 1 )
{
FT_TRACE2(( "glyph count mismatch! loca: %d, maxp: %d\n",
- face->num_locations, face->root.num_glyphs ));
+ face->num_locations - 1, face->root.num_glyphs ));
/* we only handle the case where `maxp' gives a larger value */
- if ( face->num_locations < (FT_ULong)face->root.num_glyphs )
+ if ( face->num_locations <= (FT_ULong)face->root.num_glyphs )
{
- FT_Long new_loca_len = (FT_Long)face->root.num_glyphs << shift;
+ FT_Long new_loca_len =
+ ( (FT_Long)( face->root.num_glyphs ) + 1 ) << shift;
TT_Table entry = face->dir_tables;
TT_Table limit = entry + face->num_tables;
@@ -137,9 +138,15 @@
dist = diff;
}
+ if ( entry == limit )
+ {
+ /* `loca' is the last table */
+ dist = stream->size - pos;
+ }
+
if ( new_loca_len <= dist )
{
- face->num_locations = face->root.num_glyphs;
+ face->num_locations = face->root.num_glyphs + 1;
table_len = new_loca_len;
FT_TRACE2(( "adjusting num_locations to %d\n",
@@ -203,6 +210,26 @@
}
}
+ /* 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",
+ pos1, gindex, face->glyf_len ));
+ *asize = 0;
+ return 0;
+ }
+
+ 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;
+ }
+
/* The `loca' table must be ordered; it refers to the length of */
/* an entry as the difference between the current and the next */
/* position. However, there do exist (malformed) fonts which */
@@ -269,7 +296,7 @@
face->cvt_size = 0;
face->cvt = NULL;
- error = TT_Err_Ok;
+ error = FT_Err_Ok;
goto Exit;
}
@@ -287,7 +314,7 @@
FT_Short* limit = cur + face->cvt_size;
- for ( ; cur < limit; cur++ )
+ for ( ; cur < limit; cur++ )
*cur = FT_GET_SHORT();
}
@@ -307,7 +334,7 @@
FT_UNUSED( face );
FT_UNUSED( stream );
- return TT_Err_Ok;
+ return FT_Err_Ok;
#endif
}
@@ -348,7 +375,7 @@
{
face->font_program = NULL;
face->font_program_size = 0;
- error = TT_Err_Ok;
+ error = FT_Err_Ok;
FT_TRACE2(( "is missing\n" ));
}
@@ -369,7 +396,7 @@
FT_UNUSED( face );
FT_UNUSED( stream );
- return TT_Err_Ok;
+ return FT_Err_Ok;
#endif
}
@@ -409,7 +436,7 @@
{
face->cvt_program = NULL;
face->cvt_program_size = 0;
- error = TT_Err_Ok;
+ error = FT_Err_Ok;
FT_TRACE2(( "is missing\n" ));
}
@@ -430,7 +457,7 @@
FT_UNUSED( face );
FT_UNUSED( stream );
- return TT_Err_Ok;
+ return FT_Err_Ok;
#endif
}
@@ -468,7 +495,7 @@
/* this table is optional */
error = face->goto_table( face, TTAG_hdmx, stream, &table_size );
if ( error || table_size < 8 )
- return TT_Err_Ok;
+ return FT_Err_Ok;
if ( FT_FRAME_EXTRACT( table_size, face->hdmx_table ) )
goto Exit;
@@ -481,9 +508,9 @@
record_size = FT_NEXT_ULONG( p );
/* The maximum number of bytes in an hdmx device record is the */
- /* maximum number of glyphs + 2; this is 0xFFFF + 2; this is */
- /* the reason why `record_size' is a long (which we read as */
- /* unsigned long for convenience). In practice, two bytes */
+ /* maximum number of glyphs + 2; this is 0xFFFF + 2, thus */
+ /* explaining why `record_size' is a long (which we read as */
+ /* unsigned long for convenience). In practice, two bytes are */
/* sufficient to hold the size value. */
/* */
/* There are at least two fonts, HANNOM-A and HANNOM-B version */
@@ -495,10 +522,12 @@
record_size &= 0xFFFFU;
/* The limit for `num_records' is a heuristic value. */
-
- if ( version != 0 || num_records > 255 || record_size > 0x10001L )
+ if ( version != 0 ||
+ num_records > 255 ||
+ record_size > 0x10001L ||
+ record_size < 4 )
{
- error = TT_Err_Invalid_File_Format;
+ error = FT_THROW( Invalid_File_Format );
goto Fail;
}
@@ -532,10 +561,10 @@
tt_face_free_hdmx( TT_Face face )
{
FT_Stream stream = face->root.stream;
- FT_Memory memory = stream ? stream->memory : NULL;
+ FT_Memory memory = stream->memory;
+
- if ( face->hdmx_record_sizes )
- FT_FREE( face->hdmx_record_sizes );
+ FT_FREE( face->hdmx_record_sizes );
FT_FRAME_RELEASE( face->hdmx_table );
}