This patch includes backports of the following git commits: CVE-2010-2497 freetype integer underflow #30082 #30083 7d3d2cc4fef72c6be9c454b3809c387e12b44cfc CVE-2010-2498 freetype invalid free #30106 8d22746c9e5af80ff4304aef440986403a5072e2 CVE-2010-2499 freetype buffer overflow #30248 #30249 c69891a1345640096fbf396e8dd567fe879ce233 f29f741efbba0a5ce2f16464f648fb8d026ed4c8 CVE-2010-2500 freetype integer overflow #30263 6305b869d86ff415a33576df6d43729673c66eee 1c70fcbc0aab13aed5bfe757553d0bbe6ab9461c CVE-2010-2519 freetype heap buffer overflow #30306 5ef20c8c1d4de12a84b50ba497c2a358c90ec44b b2ea64bcc6c385a8e8318f9c759450a07df58b6d diff -Naur freetype-2.3.12/src/base/ftobjs.c freetype-2.3.12.oden/src/base/ftobjs.c --- freetype-2.3.12/src/base/ftobjs.c 2010-01-23 13:44:16.000000000 +0100 +++ freetype-2.3.12.oden/src/base/ftobjs.c 2010-07-18 15:56:25.080809430 +0200 @@ -1548,11 +1548,25 @@ goto Exit; if ( FT_READ_USHORT( flags ) ) goto Exit; - rlen -= 2; /* the flags are part of the resource */ + FT_TRACE3(( "POST fragment[%d]: offsets=0x%08x, rlen=0x%08x, flags=0x%04x\n", + i, offsets[i], rlen, flags )); + + if ( ( flags >> 8 ) == 0 ) /* Comment, should not be loaded */ + continue; + + /* the flags are part of the resource, so rlen >= 2. */ + /* but some fonts declare rlen = 0 for empty fragment */ + if ( rlen > 2 ) + rlen -= 2; + else + rlen = 0; + if ( ( flags >> 8 ) == type ) len += rlen; else { + if ( pfb_lenpos + 3 > pfb_len + 2 ) + goto Exit2; pfb_data[pfb_lenpos ] = (FT_Byte)( len ); pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 ); pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 ); @@ -1561,6 +1575,8 @@ if ( ( flags >> 8 ) == 5 ) /* End of font mark */ break; + if ( pfb_pos + 6 > pfb_len + 2 ) + goto Exit2; pfb_data[pfb_pos++] = 0x80; type = flags >> 8; @@ -1575,12 +1591,18 @@ } error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen ); + if ( error ) + goto Exit2; pfb_pos += rlen; } + if ( pfb_pos + 2 > pfb_len + 2 ) + goto Exit2; pfb_data[pfb_pos++] = 0x80; pfb_data[pfb_pos++] = 3; + if ( pfb_lenpos + 3 > pfb_len + 2 ) + goto Exit2; pfb_data[pfb_lenpos ] = (FT_Byte)( len ); pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 ); pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 ); diff -Naur freetype-2.3.12/src/cff/cffgload.c freetype-2.3.12.oden/src/cff/cffgload.c --- freetype-2.3.12/src/cff/cffgload.c 2010-02-10 07:08:08.000000000 +0100 +++ freetype-2.3.12.oden/src/cff/cffgload.c 2010-07-18 15:56:37.591225654 +0200 @@ -2276,6 +2276,8 @@ /* this is the implementation described for `unknown' other */ /* subroutines in the Type1 spec. */ args -= 2 + ( args[-2] >> 16 ); + if ( args < stack ) + goto Stack_Underflow; break; case cff_op_pop: diff -Naur freetype-2.3.12/src/pfr/pfrgload.c freetype-2.3.12.oden/src/pfr/pfrgload.c --- freetype-2.3.12/src/pfr/pfrgload.c 2009-03-14 14:45:26.000000000 +0100 +++ freetype-2.3.12.oden/src/pfr/pfrgload.c 2010-07-18 15:56:25.090799365 +0200 @@ -268,8 +268,8 @@ { PFR_CHECK( 1 ); count = PFR_NEXT_BYTE( p ); - x_count = ( count & 15 ); - y_count = ( count >> 4 ); + x_count = count & 15; + y_count = count >> 4; } else { @@ -388,7 +388,7 @@ case 2: /* horizontal line to */ FT_TRACE6(( "- horizontal line to cx.%d", format_low )); - if ( format_low > x_count ) + if ( format_low >= x_count ) goto Failure; pos[0].x = glyph->x_control[format_low]; pos[0].y = pos[3].y; @@ -398,7 +398,7 @@ case 3: /* vertical line to */ FT_TRACE6(( "- vertical line to cy.%d", format_low )); - if ( format_low > y_count ) + if ( format_low >= y_count ) goto Failure; pos[0].x = pos[3].x; pos[0].y = glyph->y_control[format_low]; @@ -440,7 +440,7 @@ case 0: /* 8-bit index */ PFR_CHECK( 1 ); idx = PFR_NEXT_BYTE( p ); - if ( idx > x_count ) + if ( idx >= x_count ) goto Failure; cur->x = glyph->x_control[idx]; FT_TRACE7(( " cx#%d", idx )); @@ -470,7 +470,7 @@ case 0: /* 8-bit index */ PFR_CHECK( 1 ); idx = PFR_NEXT_BYTE( p ); - if ( idx > y_count ) + if ( idx >= y_count ) goto Failure; cur->y = glyph->y_control[idx]; FT_TRACE7(( " cy#%d", idx )); diff -Naur freetype-2.3.12/src/pshinter/pshalgo.c freetype-2.3.12.oden/src/pshinter/pshalgo.c --- freetype-2.3.12/src/pshinter/pshalgo.c 2009-07-03 15:28:24.000000000 +0200 +++ freetype-2.3.12.oden/src/pshinter/pshalgo.c 2010-07-18 15:56:25.090799365 +0200 @@ -1690,7 +1690,10 @@ /* process secondary hints to `selected' points */ if ( num_masks > 1 && glyph->num_points > 0 ) { - first = mask->end_point; + /* the `endchar' op can reduce the number of points */ + first = mask->end_point > glyph->num_points + ? glyph->num_points + : mask->end_point; mask++; for ( ; num_masks > 1; num_masks--, mask++ ) { @@ -1698,7 +1701,9 @@ FT_Int count; - next = mask->end_point; + next = mask->end_point > glyph->num_points + ? glyph->num_points + : mask->end_point; count = next - first; if ( count > 0 ) { diff -Naur freetype-2.3.12/src/smooth/ftgrays.c freetype-2.3.12.oden/src/smooth/ftgrays.c --- freetype-2.3.12/src/smooth/ftgrays.c 2009-07-31 18:45:19.000000000 +0200 +++ freetype-2.3.12.oden/src/smooth/ftgrays.c 2010-07-18 15:56:25.090799365 +0200 @@ -1007,45 +1007,40 @@ const FT_Vector* control2, const FT_Vector* to ) { - TPos dx, dy, da, db; + TPos dx, dy; + TPos mid_x, mid_y; int top, level; int* levels; FT_Vector* arc; - dx = DOWNSCALE( ras.x ) + to->x - ( control1->x << 1 ); - if ( dx < 0 ) - dx = -dx; - dy = DOWNSCALE( ras.y ) + to->y - ( control1->y << 1 ); - if ( dy < 0 ) - dy = -dy; - if ( dx < dy ) - dx = dy; - da = dx; + /* Calculate midpoint and compare it with start and end. */ + mid_x = ( DOWNSCALE( ras.x ) + to->x + + 3 * ( control1->x + control2->x ) ) / 8; + mid_y = ( DOWNSCALE( ras.y ) + to->y + + 3 * ( control1->y + control2->y ) ) / 8; - dx = DOWNSCALE( ras.x ) + to->x - 3 * ( control1->x + control2->x ); + dx = DOWNSCALE( ras.x ) + to->x - ( mid_x << 1 ); if ( dx < 0 ) dx = -dx; - dy = DOWNSCALE( ras.y ) + to->y - 3 * ( control1->x + control2->y ); + dy = DOWNSCALE( ras.y ) + to->y - ( mid_y << 1 ); if ( dy < 0 ) dy = -dy; if ( dx < dy ) dx = dy; - db = dx; + /* Check whether an approximation with straight lines is sufficient. */ level = 1; - da = da / ras.cubic_level; - db = db / ras.conic_level; - while ( da > 0 || db > 0 ) + dx = dx / ras.conic_level; + while ( dx > 0 ) { - da >>= 2; - db >>= 3; + dx >>= 3; level++; } if ( level <= 1 ) { - TPos to_x, to_y, mid_x, mid_y; + TPos to_x, to_y; to_x = UPSCALE( to->x ); @@ -1104,7 +1099,7 @@ Draw: { - TPos to_x, to_y, mid_x, mid_y; + TPos to_x, to_y; to_x = arc[0].x; @@ -1189,7 +1184,7 @@ /* first of all, compute the scanline offset */ p = (unsigned char*)map->buffer - y * map->pitch; if ( map->pitch >= 0 ) - p += ( map->rows - 1 ) * map->pitch; + p += (unsigned)( ( map->rows - 1 ) * map->pitch ); for ( ; count > 0; count--, spans++ ) { diff -Naur freetype-2.3.12/src/smooth/ftsmooth.c freetype-2.3.12.oden/src/smooth/ftsmooth.c --- freetype-2.3.12/src/smooth/ftsmooth.c 2009-07-31 18:45:19.000000000 +0200 +++ freetype-2.3.12.oden/src/smooth/ftsmooth.c 2010-07-18 16:07:09.161438297 +0200 @@ -200,7 +200,7 @@ /* Required check is ( pitch * height < FT_ULONG_MAX ), */ /* but we care realistic cases only. Always pitch <= width. */ - if ( width > 0xFFFFU || height > 0xFFFFU ) + if ( width > 0x7FFFU || height > 0x7FFFU ) { FT_ERROR(( "ft_smooth_render_generic: glyph too large: %d x %d\n", width, height ));