summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWerner Lemberg <wl@gnu.org>2016-09-09 22:11:07 +0200
committerWerner Lemberg <wl@gnu.org>2016-09-09 22:11:07 +0200
commitd609b7c1582a9714bbad831fc5f955bccca436a4 (patch)
treee1161ad639f7527984a427529f60b40919b2c7db /src
parentd2d5968aed5bc264c885c54d0a50e5355808ab78 (diff)
downloadfreetype2-d609b7c1582a9714bbad831fc5f955bccca436a4.tar.gz
[sfnt] Don't provide (completely) broken strike data.
FreeType tries to sanitize strike header data; we now reject completely broken ones. * include/freetype/internal/tttypes.h (TT_FaceRec): New `sbit_strike_map' array pointer. * src/base/ftobjs.c (FT_Match_Size): Reject matches where either width or height would be zero. Add tracing message in case of error. * src/sfnt/sfobjs.c (sfnt_load_face): Populate `sbit_strike_map', only using (more or less) valid strike header data for FT_Face's `available_sizes' array. (sfnt_done_face): Updated. * src/sfnt/ttsbit.c (tt_face_set_sbit_strike): Use `sbit_strike_map'. (tt_face_load_strike_metrics): Improve tracing. * src/truetype/ttdriver.c (tt_size_select): Use `sbit_strike_map'.
Diffstat (limited to 'src')
-rw-r--r--src/base/ftobjs.c5
-rw-r--r--src/sfnt/sfobjs.c31
-rw-r--r--src/sfnt/ttsbit.c12
-rw-r--r--src/truetype/ttdriver.c10
4 files changed, 44 insertions, 14 deletions
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index 0c9e4090c..9006b598b 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -2631,6 +2631,9 @@
w = FT_PIX_ROUND( w );
h = FT_PIX_ROUND( h );
+ if ( !w || !h )
+ return FT_THROW( Invalid_Pixel_Size );
+
for ( i = 0; i < face->num_fixed_sizes; i++ )
{
FT_Bitmap_Size* bsize = face->available_sizes + i;
@@ -2650,6 +2653,8 @@
}
}
+ FT_TRACE3(( "FT_Match_Size: no matching bitmap strike\n" ));
+
return FT_THROW( Invalid_Pixel_Size );
}
diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c
index 4413bbcf2..5d5a448d8 100644
--- a/src/sfnt/sfobjs.c
+++ b/src/sfnt/sfobjs.c
@@ -1411,7 +1411,7 @@
* depths in the FT_Bitmap_Size record. This is a design error.
*/
{
- FT_UInt i, count;
+ FT_UInt count;
count = face->sbit_num_strikes;
@@ -1423,6 +1423,8 @@
FT_Short avgwidth = face->os2.xAvgCharWidth;
FT_Size_Metrics metrics;
+ FT_UInt strike_idx, bsize_idx;
+
if ( em_size == 0 || face->os2.version == 0xFFFFU )
{
@@ -1430,31 +1432,43 @@
em_size = 1;
}
- if ( FT_NEW_ARRAY( root->available_sizes, count ) )
+ /* to avoid invalid strike data in the `available_sizes' field */
+ /* of `FT_Face', we map `available_sizes' indices to strike */
+ /* indices */
+ if ( FT_NEW_ARRAY( root->available_sizes, count ) ||
+ FT_NEW_ARRAY( face->sbit_strike_map, count ) )
goto Exit;
- for ( i = 0; i < count; i++ )
+ bsize_idx = 0;
+ for ( strike_idx = 0; strike_idx < count; strike_idx++ )
{
- FT_Bitmap_Size* bsize = root->available_sizes + i;
+ FT_Bitmap_Size* bsize = root->available_sizes + bsize_idx;
- error = sfnt->load_strike_metrics( face, i, &metrics );
+ error = sfnt->load_strike_metrics( face, strike_idx, &metrics );
if ( error )
goto Exit;
bsize->height = (FT_Short)( metrics.height >> 6 );
- bsize->width = (FT_Short)(
- ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size );
+ bsize->width = (FT_Short)(
+ ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size );
bsize->x_ppem = metrics.x_ppem << 6;
bsize->y_ppem = metrics.y_ppem << 6;
/* assume 72dpi */
bsize->size = metrics.y_ppem << 6;
+
+ /* only use strikes with valid PPEM values */
+ if ( bsize->x_ppem && bsize->y_ppem )
+ face->sbit_strike_map[bsize_idx++] = strike_idx;
}
+ /* reduce array size to the actually used elements */
+ (void)FT_RENEW_ARRAY( face->sbit_strike_map, count, bsize_idx );
+
root->face_flags |= FT_FACE_FLAG_FIXED_SIZES;
- root->num_fixed_sizes = (FT_Int)count;
+ root->num_fixed_sizes = (FT_Int)bsize_idx;
}
}
@@ -1648,6 +1662,7 @@
/* freeing sbit size table */
FT_FREE( face->root.available_sizes );
+ FT_FREE( face->sbit_strike_map );
face->root.num_fixed_sizes = 0;
FT_FREE( face->postscript_name );
diff --git a/src/sfnt/ttsbit.c b/src/sfnt/ttsbit.c
index 36c261dcc..b4902be69 100644
--- a/src/sfnt/ttsbit.c
+++ b/src/sfnt/ttsbit.c
@@ -251,7 +251,14 @@
FT_Size_Request req,
FT_ULong* astrike_index )
{
- return FT_Match_Size( (FT_Face)face, req, 0, astrike_index );
+ FT_Error error;
+
+
+ error = FT_Match_Size( (FT_Face)face, req, 0, astrike_index );
+ if ( !error )
+ *astrike_index = face->sbit_strike_map[*astrike_index];
+
+ return error;
}
@@ -305,7 +312,8 @@
FT_TRACE2(( "tt_face_load_strike_metrics:"
" sanitizing invalid ascender and descender\n"
" "
- " values for strike (%d, %d)\n",
+ " values for strike %d (%dppem, %dppem)\n",
+ strike_index,
metrics->x_ppem, metrics->y_ppem ));
/* sanitize buggy ascender and descender values */
diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c
index 6520c93df..8c988670c 100644
--- a/src/truetype/ttdriver.c
+++ b/src/truetype/ttdriver.c
@@ -273,25 +273,27 @@
static FT_Error
tt_size_select( FT_Size size,
- FT_ULong strike_index )
+ FT_ULong bsize_index )
{
TT_Face ttface = (TT_Face)size->face;
TT_Size ttsize = (TT_Size)size;
FT_Error error = FT_Err_Ok;
+ FT_UInt strike_index = ttface->sbit_strike_map[bsize_index];
+
ttsize->strike_index = strike_index;
if ( FT_IS_SCALABLE( size->face ) )
{
/* use the scaled metrics, even when tt_size_reset fails */
- FT_Select_Metrics( size->face, strike_index );
+ FT_Select_Metrics( size->face, bsize_index );
tt_size_reset( ttsize ); /* ignore return value */
}
else
{
- SFNT_Service sfnt = (SFNT_Service) ttface->sfnt;
+ SFNT_Service sfnt = (SFNT_Service)ttface->sfnt;
FT_Size_Metrics* metrics = &size->metrics;
@@ -319,7 +321,7 @@
if ( FT_HAS_FIXED_SIZES( size->face ) )
{
TT_Face ttface = (TT_Face)size->face;
- SFNT_Service sfnt = (SFNT_Service) ttface->sfnt;
+ SFNT_Service sfnt = (SFNT_Service)ttface->sfnt;
FT_ULong strike_index;