From e421a0bffc13299f3d8f0229a312991d85bcc23a Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Sat, 10 Sep 2016 08:02:30 +0200 Subject: [PATCH] [sfnt] Fix previous commit. Problems reported as https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=40 We now map the strike index right before accessing the physical data, not earlier. * src/sfnt/sfobjs.c (sfnt_load_face): Set `face->sbit_strike_map' after creating the map so that... * src/sfnt/ttsbit.c (tt_face_load_strike_metrics): ... this function can be used before and after setting up `sbit_strike_map'. (tt_face_set_sbit_strike): Revert change. (tt_sbit_decoder_init, tt_face_load_sbix_image): Map strike index. * src/truetype/ttdriver.c (tt_size_select): Revert change. --- ChangeLog | 21 +++++++++++++++++++++ src/sfnt/sfobjs.c | 22 +++++++++++++++------- src/sfnt/ttsbit.c | 31 +++++++++++++++++++++---------- src/truetype/ttdriver.c | 6 ++---- 4 files changed, 59 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6beb471c5..b4e80ca86 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2016-09-10 Werner Lemberg + + [sfnt] Fix previous commit. + + Problems reported as + + https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=40 + + We now map the strike index right before accessing the physical + data, not earlier. + + * src/sfnt/sfobjs.c (sfnt_load_face): Set `face->sbit_strike_map' + after creating the map so that... + + * src/sfnt/ttsbit.c (tt_face_load_strike_metrics): ... this function + can be used before and after setting up `sbit_strike_map'. + (tt_face_set_sbit_strike): Revert change. + (tt_sbit_decoder_init, tt_face_load_sbix_image): Map strike index. + + * src/truetype/ttdriver.c (tt_size_select): Revert change. + 2016-09-09 Werner Lemberg [ftfuzzer] Minor improvements. diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c index 5d5a448d8..ceeae207b 100644 --- a/src/sfnt/sfobjs.c +++ b/src/sfnt/sfobjs.c @@ -1423,7 +1423,8 @@ FT_Short avgwidth = face->os2.xAvgCharWidth; FT_Size_Metrics metrics; - FT_UInt strike_idx, bsize_idx; + FT_UInt* sbit_strike_map = NULL; + FT_UInt strike_idx, bsize_idx; if ( em_size == 0 || face->os2.version == 0xFFFFU ) @@ -1436,7 +1437,7 @@ /* 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 ) ) + FT_NEW_ARRAY( sbit_strike_map, count ) ) goto Exit; bsize_idx = 0; @@ -1447,7 +1448,7 @@ error = sfnt->load_strike_metrics( face, strike_idx, &metrics ); if ( error ) - goto Exit; + continue; bsize->height = (FT_Short)( metrics.height >> 6 ); bsize->width = (FT_Short)( @@ -1461,14 +1462,21 @@ /* only use strikes with valid PPEM values */ if ( bsize->x_ppem && bsize->y_ppem ) - face->sbit_strike_map[bsize_idx++] = strike_idx; + 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 ); + (void)FT_RENEW_ARRAY( sbit_strike_map, count, bsize_idx ); - root->face_flags |= FT_FACE_FLAG_FIXED_SIZES; - root->num_fixed_sizes = (FT_Int)bsize_idx; + /* from now on, all strike indices are mapped */ + /* using `sbit_strike_map' */ + if ( bsize_idx ) + { + face->sbit_strike_map = sbit_strike_map; + + root->face_flags |= FT_FACE_FLAG_FIXED_SIZES; + root->num_fixed_sizes = (FT_Int)bsize_idx; + } } } diff --git a/src/sfnt/ttsbit.c b/src/sfnt/ttsbit.c index b4902be69..0a9011151 100644 --- a/src/sfnt/ttsbit.c +++ b/src/sfnt/ttsbit.c @@ -251,14 +251,7 @@ FT_Size_Request req, FT_ULong* 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; + return FT_Match_Size( (FT_Face)face, req, 0, astrike_index ); } @@ -267,8 +260,22 @@ FT_ULong strike_index, FT_Size_Metrics* metrics ) { - if ( strike_index >= (FT_ULong)face->sbit_num_strikes ) - return FT_THROW( Invalid_Argument ); + /* we have to test for the existence of `sbit_strike_map' */ + /* because the function gets also used at the very beginning */ + /* to construct `sbit_strike_map' itself */ + if ( face->sbit_strike_map ) + { + if ( strike_index >= (FT_ULong)face->root.num_fixed_sizes ) + return FT_THROW( Invalid_Argument ); + + /* map to real index */ + strike_index = face->sbit_strike_map[strike_index]; + } + else + { + if ( strike_index >= (FT_ULong)face->sbit_num_strikes ) + return FT_THROW( Invalid_Argument ); + } switch ( (FT_UInt)face->sbit_table_type ) { @@ -457,6 +464,8 @@ FT_Stream stream = face->root.stream; + strike_index = face->sbit_strike_map[strike_index]; + if ( !face->ebdt_size ) goto Exit; if ( FT_STREAM_SEEK( face->ebdt_start ) ) @@ -1418,6 +1427,8 @@ FT_UNUSED( map ); + strike_index = face->sbit_strike_map[strike_index]; + metrics->width = 0; metrics->height = 0; diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c index 8c988670c..b96a2276c 100644 --- a/src/truetype/ttdriver.c +++ b/src/truetype/ttdriver.c @@ -273,21 +273,19 @@ static FT_Error tt_size_select( FT_Size size, - FT_ULong bsize_index ) + FT_ULong strike_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, bsize_index ); + FT_Select_Metrics( size->face, strike_index ); tt_size_reset( ttsize ); /* ignore return value */ }