ref: 9ca782569c218e18c420e7c13bdbdf3e9a75c87a
parent: 264f307e66f9c2763b2e31b0a4e7513b7866745a
author: David Turner <[email protected]>
date: Tue May 2 05:00:29 EDT 2006
* 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.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
2006-05-02 David Turner <[email protected]>
+ * 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
@@ -24,6 +34,7 @@
note that the memory debugger now works again when FT_DEBUG_MEMORY
is defined, and FT_STRICT_ALIASING has disappeared, the corresponding
code being now the default.
+
2006-04-30 suzuki toshiya <[email protected]>
--- a/include/freetype/internal/ftmemory.h
+++ b/include/freetype/internal/ftmemory.h
@@ -134,6 +134,19 @@
#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,11 +211,23 @@
#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 )
--- 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 )
--- 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 ) )
--- 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,6 +426,7 @@
FT_Error error;
char* newpath;
FT_Memory memory;
+ FT_Long base_file_len = ft_strlen( base_file_name );
FT_UNUSED( stream );
@@ -432,14 +433,18 @@
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;
}
--- 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 */
--- 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;
--- 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;
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -684,9 +684,10 @@
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 ) +
@@ -693,6 +694,7 @@
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 ) );
}
--- 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 )
{
--- 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;