diff --git a/ChangeLog b/ChangeLog index 91e3617eb..362b06a72 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,15 @@ 2006-05-02 David Turner + * include/freetype/internal/ftmemory.h, src/base/ftbitmap.c, + src/base/ftmac.c, src/base/ftrfork.c, src/lzw/ftzopen.c, + src/raster/ftrend1.c, src/sfnt/ttpost.c, src/truetype/ttgxvar.c, + src/type42/t42parse.c, src/winfonts/winfnt.c: hardening the code + against out-of-bounds conditions when allocating arrays. This is + for the cases where FT_NEW_ARRAY and FT_RENEW_ARRAY are not used + already. Introducing the new FT_ALLOC_MULT and FT_REALLOC_MULT + macros. + + * include/freetype/fterrdef.h, include/freetype/config/ftconfig.h, include/freetype/internal/ftmemory.h, src/base/ftdbgmem.c, src/base/ftutil.c: udpating the memory management functions and @@ -25,6 +35,7 @@ is defined, and FT_STRICT_ALIASING has disappeared, the corresponding code being now the default. + 2006-04-30 suzuki toshiya Fix bug in Mac_Read_POST_Resource() to parse PFB font with MacOS diff --git a/include/freetype/internal/ftmemory.h b/include/freetype/internal/ftmemory.h index 1fc4f9977..9ef542720 100644 --- a/include/freetype/internal/ftmemory.h +++ b/include/freetype/internal/ftmemory.h @@ -134,6 +134,19 @@ FT_BASE( long ) _ft_debug_lineno; #define FT_MEM_QRENEW_ARRAY(ptr,cur,new) \ FT_DEBUG_INNER( (ptr) = ft_mem_qrealloc( memory, sizeof(*(ptr)), (cur), (new), (ptr), &error ) ) +#define FT_MEM_ALLOC_MULT(ptr,count,item_size) \ + FT_DEBUG_INNER( (ptr) = ft_mem_realloc( memory, (item_size), 0, (count), NULL, &error ) ) + +#define FT_MEM_REALLOC_MULT(ptr,oldcnt,newcnt,itmsz) \ + FT_DEBUG_INNER( (ptr) = ft_mem_realloc( memory, (itmsz), (oldcnt), (newcnt), (ptr), &error ) ) + +#define FT_MEM_QALLOC_MULT(ptr,count,item_size) \ + FT_DEBUG_INNER( (ptr) = ft_mem_qrealloc( memory, (item_size), 0, (count), NULL, &error ) ) + +#define FT_MEM_QREALLOC_MULT(ptr,oldcnt,newcnt,itmsz) \ + FT_DEBUG_INNER( (ptr) = ft_mem_qrealloc( memory, (itmsz), (oldcnt), (newcnt), (ptr), &error ) ) + + #define FT_MEM_SET_ERROR( cond ) ( (cond), error != 0 ) @@ -198,12 +211,24 @@ FT_BASE( long ) _ft_debug_lineno; #define FT_REALLOC(ptr,cursz,newsz) \ FT_MEM_SET_ERROR( FT_MEM_REALLOC(ptr,cursz,newsz) ) +#define FT_ALLOC_MULT(ptr,count,item_size) \ + FT_MEM_SET_ERROR( FT_MEM_ALLOC_MULT(ptr,count,item_size) ) + +#define FT_REALLOC_MULT(ptr,oldcnt,newcnt,itmsz) \ + FT_MEM_SET_ERROR( FT_MEM_REALLOC_MULT(ptr,oldcnt,newcnt,itmsz) ) + #define FT_QALLOC(ptr,size) \ FT_MEM_SET_ERROR( FT_MEM_QALLOC(ptr,size) ) #define FT_QREALLOC(ptr,cursz,newsz) \ FT_MEM_SET_ERROR( FT_MEM_QREALLOC(ptr,cursz,newsz) ) +#define FT_QALLOC_MULT(ptr,count,item_size) \ + FT_MEM_SET_ERROR( FT_MEM_QALLOC_MULT(ptr,count,item_size) ) + +#define FT_QREALLOC_MULT(ptr,oldcnt,newcnt,itmsz) \ + FT_MEM_SET_ERROR( FT_MEM_QREALLOC_MULT(ptr,oldcnt,newcnt,itmsz) ) + #define FT_FREE(ptr) FT_MEM_FREE( ptr ) #define FT_NEW(ptr) \ diff --git a/src/base/ftbitmap.c b/src/base/ftbitmap.c index 7a8829438..d4709a440 100644 --- a/src/base/ftbitmap.c +++ b/src/base/ftbitmap.c @@ -165,7 +165,7 @@ new_pitch = ( bitmap->width + xpixels + ppb - 1 ) / ppb; - if ( FT_ALLOC( buffer, new_pitch * ( bitmap->rows + ypixels ) ) ) + if ( FT_QALLOC_MULT( buffer, new_pitch, bitmap->rows + ypixels ) ) return error; if ( bitmap->pitch > 0 ) diff --git a/src/base/ftmac.c b/src/base/ftmac.c index 5aed8965e..6e4cbe577 100644 --- a/src/base/ftmac.c +++ b/src/base/ftmac.c @@ -808,6 +808,7 @@ short res_id; unsigned char *buffer, *p, *size_p = NULL; FT_ULong total_size = 0; + FT_ULong old_total_size = 0; FT_ULong post_size, pfb_chunk_size; Handle post_data; char code, last_code; @@ -838,6 +839,15 @@ total_size += GetHandleSize( post_data ) - 2; last_code = code; + + /* detect integer overflows */ + if ( total_size < old_total_size ) + { + error = FT_Err_Array_Too_Large; + goto Error; + } + + old_total_size = total_size; } if ( FT_ALLOC( buffer, (FT_Long)total_size ) ) diff --git a/src/base/ftrfork.c b/src/base/ftrfork.c index 5d44ca456..cfa5891c4 100644 --- a/src/base/ftrfork.c +++ b/src/base/ftrfork.c @@ -179,7 +179,7 @@ if ( error ) return error; - if ( FT_ALLOC( offsets_internal, *count * sizeof( FT_Long ) ) ) + if ( FT_NEW_ARRAY( offsets_internal, *count ) ) return error; for ( j = 0; j < *count; ++j ) @@ -426,20 +426,25 @@ FT_Error error; char* newpath; FT_Memory memory; + FT_Long base_file_len = ft_strlen( base_file_name ); FT_UNUSED( stream ); memory = library->memory; - if ( FT_ALLOC( newpath, - ft_strlen( base_file_name ) + ft_strlen( "/rsrc" ) + 1 ) ) + if ( base_file_len > FT_INT_MAX ) + return FT_Err_Array_Too_Large; + + if ( FT_ALLOC( newpath, base_file_len + 6 ) ) return error; - ft_strcpy( newpath, base_file_name ); - ft_strcat( newpath, "/rsrc" ); + FT_MEM_COPY( newpath, base_file_name, base_file_len ); + FT_MEM_COPY( newpath + base_file_len, "/rsrc", 6 ); + *result_file_name = newpath; - *result_offset = 0; + *result_offset = 0; + return FT_Err_Ok; } diff --git a/src/lzw/ftzopen.c b/src/lzw/ftzopen.c index 4105cfa1e..1d29fd821 100644 --- a/src/lzw/ftzopen.c +++ b/src/lzw/ftzopen.c @@ -127,10 +127,8 @@ * to write it literally. * */ - if ( FT_REALLOC( - state->prefix, - old_size * (sizeof ( FT_UShort ) + sizeof ( FT_Byte ) ), - new_size * (sizeof ( FT_UShort ) + sizeof ( FT_Byte ) ) ) ) + if ( FT_REALLOC_MULT( state->prefix, old_size, new_size, + sizeof(FT_UShort)+sizeof(FT_Byte) ) ) return -1; /* now adjust `suffix' and move the data accordingly */ diff --git a/src/raster/ftrend1.c b/src/raster/ftrend1.c index ed75fb605..4e8d10f3e 100644 --- a/src/raster/ftrend1.c +++ b/src/raster/ftrend1.c @@ -161,13 +161,13 @@ if ( !( mode & FT_RENDER_MODE_MONO ) ) { /* we pad to 32 bits, only for backwards compatibility with FT 1.x */ - pitch = FT_PAD_CEIL( width, 4 ); + pitch = FT_PAD_CEIL( width, 4 ); bitmap->pixel_mode = FT_PIXEL_MODE_GRAY; bitmap->num_grays = 256; } else { - pitch = ( ( width + 15 ) >> 4 ) << 1; + pitch = ( ( width + 15 ) >> 4 ) << 1; bitmap->pixel_mode = FT_PIXEL_MODE_MONO; } @@ -175,7 +175,7 @@ bitmap->rows = height; bitmap->pitch = pitch; - if ( FT_ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) ) + if ( FT_ALLOC_MULT( bitmap->buffer, pitch, height ) ) goto Exit; slot->internal->flags |= FT_GLYPH_OWN_BITMAP; diff --git a/src/sfnt/ttpost.c b/src/sfnt/ttpost.c index 39f99163f..511288e34 100644 --- a/src/sfnt/ttpost.c +++ b/src/sfnt/ttpost.c @@ -292,7 +292,7 @@ goto Exit; } - if ( FT_ALLOC( offset_table, num_glyphs ) || + if ( FT_NEW_ARRAY( offset_table, num_glyphs ) || FT_STREAM_READ( offset_table, num_glyphs ) ) goto Fail; diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c index fe5eaa312..0e7243559 100644 --- a/src/truetype/ttgxvar.c +++ b/src/truetype/ttgxvar.c @@ -684,15 +684,17 @@ goto Exit; } - if ( FT_ALLOC( face->blend, sizeof ( GX_BlendRec ) ) ) + if ( FT_NEW( face->blend ) ) goto Exit; + /* XXX: TODO - check for overflows */ face->blend->mmvar_len = sizeof ( FT_MM_Var ) + fvar_head.axisCount * sizeof ( FT_Var_Axis ) + fvar_head.instanceCount * sizeof ( FT_Var_Named_Style ) + fvar_head.instanceCount * fvar_head.axisCount * sizeof ( FT_Fixed ) + 5 * fvar_head.axisCount; + if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) ) goto Exit; face->blend->mmvar = mmvar; @@ -1253,7 +1255,7 @@ for ( j = 0; j < point_count; ++j ) { int pindex = localpoints[j]; - + face->cvt[pindex] = (FT_Short)( face->cvt[pindex] + FT_MulFix( deltas[j], apply ) ); } diff --git a/src/type42/t42parse.c b/src/type42/t42parse.c index 80e7547b9..b589f198e 100644 --- a/src/type42/t42parse.c +++ b/src/type42/t42parse.c @@ -623,6 +623,7 @@ status = OTHER_TABLES; face->ttf_size = ttf_size; + /* there are no more than 256 tables, so no size check here */ if ( FT_REALLOC( face->ttf_data, 12 + 16 * num_tables, ttf_size + 1 ) ) goto Fail; @@ -1071,7 +1072,7 @@ if ( !name ) continue; - if ( cur[0] == name[0] && + if ( cur[0] == name[0] && len == (FT_PtrDist)ft_strlen( (const char *)name ) && ft_memcmp( cur, name, len ) == 0 ) { diff --git a/src/winfonts/winfnt.c b/src/winfonts/winfnt.c index 553cddbc0..3523b14f8 100644 --- a/src/winfonts/winfnt.c +++ b/src/winfonts/winfnt.c @@ -531,7 +531,7 @@ /* reserve one slot for the .notdef glyph at index 0 */ root->num_glyphs = font->header.last_char - - font->header.first_char + 1 + 1; + font->header.first_char + 1 + 1; /* Some broken fonts don't delimit the face name with a final */ /* NULL byte -- the frame is erroneously one byte too small. */ @@ -540,14 +540,18 @@ family_size = font->header.file_size - font->header.face_name_offset; if ( FT_ALLOC( font->family_name, family_size + 1 ) ) goto Fail; + FT_MEM_COPY( font->family_name, font->fnt_frame + font->header.face_name_offset, family_size ); + font->family_name[family_size] = '\0'; + if ( FT_REALLOC( font->family_name, family_size, ft_strlen( font->family_name ) + 1 ) ) goto Fail; + root->family_name = font->family_name; root->style_name = (char *)"Regular"; @@ -693,7 +697,7 @@ /* note: since glyphs are stored in columns and not in rows we */ /* can't use ft_glyphslot_set_bitmap */ - if ( FT_ALLOC( bitmap->buffer, pitch * bitmap->rows ) ) + if ( FT_ALLOC_MULT( bitmap->buffer, pitch, bitmap->rows ) ) goto Exit; column = (FT_Byte*)bitmap->buffer;