From 88ab638e0fd4cdc5cdb40d5dc0897ec064ce9719 Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Thu, 7 Jun 2007 05:01:56 +0000 Subject: [PATCH] * src/sfnt/ttsbit0.c (tt_sbit_decoder_init, tt_sbit_decoder_load_image): Protect against integer overflows. * src/pfr/pfrgload.c (pfr_glyph_load_simple): More bounding checks for `x_control' and `y_control'. --- ChangeLog | 9 +++++++++ src/pfr/pfrgload.c | 27 ++++++++++++++----------- src/sfnt/ttsbit0.c | 49 ++++++++++++++++++++++++++++++++++++---------- 3 files changed, 64 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index c26bf5e79..911ebc878 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2007-06-07 Werner Lemberg + + * src/sfnt/ttsbit0.c (tt_sbit_decoder_init, + tt_sbit_decoder_load_image): Protect against integer overflows. + + + * src/pfr/pfrgload.c (pfr_glyph_load_simple): More bounding checks + for `x_control' and `y_control'. + 2007-06-06 Werner Lemberg * src/base/ftoutln.c (FT_Outline_Decompose): Check `last'. diff --git a/src/pfr/pfrgload.c b/src/pfr/pfrgload.c index d92c30a06..3bb173302 100644 --- a/src/pfr/pfrgload.c +++ b/src/pfr/pfrgload.c @@ -354,14 +354,15 @@ for (;;) { - FT_Int format, args_format = 0, args_count, n; + FT_UInt format, format_low, args_format = 0, args_count, n; /***************************************************************/ /* read instruction */ /* */ PFR_CHECK( 1 ); - format = PFR_NEXT_BYTE( p ); + format = PFR_NEXT_BYTE( p ); + format_low = format & 15; switch ( format >> 4 ) { @@ -381,30 +382,34 @@ case 5: /* move to outside contour */ FT_TRACE6(( "- move to outside" )); Line1: - args_format = format & 15; + args_format = format_low; args_count = 1; break; case 2: /* horizontal line to */ - FT_TRACE6(( "- horizontal line to cx.%d", format & 15 )); + FT_TRACE6(( "- horizontal line to cx.%d", format_low )); + if ( format_low > x_count ) + goto Failure; + pos[0].x = glyph->x_control[format_low]; pos[0].y = pos[3].y; - pos[0].x = glyph->x_control[format & 15]; pos[3] = pos[0]; args_count = 0; break; case 3: /* vertical line to */ - FT_TRACE6(( "- vertical line to cy.%d", format & 15 )); + FT_TRACE6(( "- vertical line to cy.%d", format_low )); + if ( format_low > y_count ) + goto Failure; pos[0].x = pos[3].x; - pos[0].y = glyph->y_control[format & 15]; - pos[3] = pos[0]; + pos[0].y = glyph->y_control[format_low]; + pos[3] = pos[0]; args_count = 0; break; case 6: /* horizontal to vertical curve */ FT_TRACE6(( "- hv curve " )); - args_format = 0xB8E; - args_count = 3; + args_format = 0xB8E; + args_count = 3; break; case 7: /* vertical to horizontal curve */ @@ -416,7 +421,7 @@ default: /* general curve to */ FT_TRACE6(( "- general curve" )); args_count = 4; - args_format = format & 15; + args_format = format_low; } /***********************************************************/ diff --git a/src/sfnt/ttsbit0.c b/src/sfnt/ttsbit0.c index edbfa103d..f8adc64a7 100644 --- a/src/sfnt/ttsbit0.c +++ b/src/sfnt/ttsbit0.c @@ -235,7 +235,7 @@ TT_SBit_MetricsRec* metrics ) { FT_Error error; - FT_Stream stream = face->root.stream; + FT_Stream stream = face->root.stream; FT_ULong ebdt_size; @@ -261,14 +261,27 @@ /* now find the strike corresponding to the index */ { - FT_Byte* p = decoder->eblc_base + 8 + 48 * strike_index; + FT_Byte* p; + + if ( 8 + 48 * strike_index + 3 * 4 + 34 + 1 > face->sbit_table_size ) + { + error = SFNT_Err_Invalid_File_Format; + goto Exit; + } + + p = decoder->eblc_base + 8 + 48 * strike_index; decoder->strike_index_array = FT_NEXT_ULONG( p ); p += 4; decoder->strike_index_count = FT_NEXT_ULONG( p ); p += 34; decoder->bit_depth = *p; + + if ( decoder->strike_index_array > face->sbit_table_size || + decoder->strike_index_array + 8 * decoder->strike_index_count > + face->sbit_table_size ) + error = SFNT_Err_Invalid_File_Format; } Exit: @@ -642,9 +655,9 @@ for ( nn = 0; nn < num_components; nn++ ) { - FT_UInt gindex = FT_NEXT_USHORT( p ); - FT_Byte dx = FT_NEXT_BYTE( p ); - FT_Byte dy = FT_NEXT_BYTE( p ); + FT_UInt gindex = FT_NEXT_USHORT( p ); + FT_Byte dx = FT_NEXT_BYTE( p ); + FT_Byte dy = FT_NEXT_BYTE( p ); /* NB: a recursive call */ @@ -775,9 +788,6 @@ FT_ULong image_start = 0, image_end = 0, image_offset; - if ( p + 8 * num_ranges > p_limit ) - goto NoBitmap; - for ( ; num_ranges > 0; num_ranges-- ) { start = FT_NEXT_USHORT( p ); @@ -792,6 +802,12 @@ FoundRange: image_offset = FT_NEXT_ULONG( p ); + + /* overflow check */ + if ( decoder->eblc_base + decoder->strike_index_array + image_offset < + decoder->eblc_base ) + goto Failure; + p = decoder->eblc_base + decoder->strike_index_array + image_offset; if ( p + 8 > p_limit ) goto NoBitmap; @@ -831,7 +847,7 @@ goto NoBitmap; image_start = image_size * ( glyph_index - start ); - image_end = image_start + image_size; + image_end = image_start + image_size; } break; @@ -858,6 +874,11 @@ goto NoBitmap; num_glyphs = FT_NEXT_ULONG( p ); + + /* overflow check */ + if ( p + ( num_glyphs + 1 ) * 4 < p ) + goto Failure; + if ( p + ( num_glyphs + 1 ) * 4 > p_limit ) goto NoBitmap; @@ -895,6 +916,11 @@ goto NoBitmap; num_glyphs = FT_NEXT_ULONG( p ); + + /* overflow check */ + if ( p + 2 * num_glyphs < p ) + goto Failure; + if ( p + 2 * num_glyphs > p_limit ) goto NoBitmap; @@ -910,7 +936,7 @@ if ( mm >= num_glyphs ) goto NoBitmap; - image_start = image_size*mm; + image_start = image_size * mm; image_end = image_start + image_size; } break; @@ -932,6 +958,9 @@ x_pos, y_pos ); + Failure: + return SFNT_Err_Invalid_Table; + NoBitmap: return SFNT_Err_Invalid_Argument; }