@ -50,8 +50,15 @@ THE SOFTWARE.
# ifdef FT_DEBUG_LEVEL_TRACE
static const char * const tableNames [ ] =
{
" prop " , " accl " , " mtrcs " , " bmps " , " imtrcs " ,
" enc " , " swidth " , " names " , " accel "
" properties " ,
" accelerators " ,
" metrics " ,
" bitmaps " ,
" ink metrics " ,
" encodings " ,
" swidths " ,
" glyph names " ,
" BDF accelerators "
} ;
# endif
@ -109,22 +116,20 @@ THE SOFTWARE.
if ( stream - > size < 16 )
return FT_THROW ( Invalid_File_Format ) ;
/* We need 16 bytes per TOC entry. Additionally, as a */
/* heuristic protection against gzip bombs (i.e., very */
/* small input files that expand to insanely large */
/* files), we limit the number of TOC entries to 1024. */
if ( toc - > count > stream - > size > > 4 | |
toc - > count > 1024 )
/* we need 16 bytes per TOC entry, */
/* and there can be most 9 tables */
if ( toc - > count > ( stream - > size > > 4 ) | |
toc - > count > 9 )
{
FT_TRACE0 ( ( " pcf_read_TOC: adjusting number of tables "
" (from %d to %d) \n " ,
toc - > count ,
FT_MIN ( stream - > size > > 4 , 1024 ) ) ) ;
toc - > count = FT_MIN ( stream - > size > > 4 , 1024 ) ;
FT_MIN ( stream - > size > > 4 , 9 ) ) ) ;
toc - > count = FT_MIN ( stream - > size > > 4 , 9 ) ;
}
if ( FT_NEW_ARRAY ( face - > toc . tables , toc - > count ) )
return FT_THROW ( Out_Of_Memory ) ;
return error ;
tables = face - > toc . tables ;
for ( n = 0 ; n < toc - > count ; n + + )
@ -237,8 +242,8 @@ THE SOFTWARE.
if ( tables [ i ] . type = = ( FT_UInt ) ( 1 < < j ) )
name = tableNames [ j ] ;
FT_TRACE4 ( ( " %d: type=%s, format=0x%X, "
" size=%ld (0x%lX), offset=%ld (0x%lX) \n " ,
FT_TRACE4 ( ( " %d: type=%s, format=0x%X, "
" size=%ld (0x%lX), offset=%ld (0x%lX)\n " ,
i , name ,
tables [ i ] . format ,
tables [ i ] . size , tables [ i ] . size ,
@ -348,6 +353,17 @@ THE SOFTWARE.
metric - > attributes = 0 ;
}
FT_TRACE5 ( ( " width=%d, "
" lsb=%d, rsb=%d, "
" ascent=%d, descent=%d, "
" attributes=%d \n " ,
metric - > characterWidth ,
metric - > leftSideBearing ,
metric - > rightSideBearing ,
metric - > ascent ,
metric - > descent ,
metric - > attributes ) ) ;
Exit :
return error ;
}
@ -466,7 +482,7 @@ THE SOFTWARE.
{
PCF_ParseProperty props = NULL ;
PCF_Property properties = NULL ;
FT_ULong nprops , i ;
FT_ULong nprops , orig_nprops , i ;
FT_ULong format , size ;
FT_Error error ;
FT_Memory memory = FT_FACE ( face ) - > memory ;
@ -486,32 +502,43 @@ THE SOFTWARE.
if ( FT_READ_ULONG_LE ( format ) )
goto Bail ;
FT_TRACE4 ( ( " pcf_get_properties: \n " ) ) ;
FT_TRACE4 ( ( " format = %ld \n " , format ) ) ;
FT_TRACE4 ( ( " pcf_get_properties: \n "
" format: 0x%lX (%s) \n " ,
format ,
PCF_BYTE_ORDER ( format ) = = MSBFirst ? " MSB " : " LSB " ) ) ;
if ( ! PCF_FORMAT_MATCH ( format , PCF_DEFAULT_FORMAT ) )
goto Bail ;
if ( PCF_BYTE_ORDER ( format ) = = MSBFirst )
( void ) FT_READ_ULONG ( nprops ) ;
( void ) FT_READ_ULONG ( orig_ nprops ) ;
else
( void ) FT_READ_ULONG_LE ( nprops ) ;
( void ) FT_READ_ULONG_LE ( orig_ nprops ) ;
if ( error )
goto Bail ;
FT_TRACE4 ( ( " nprop = %d (truncate %d props) \n " ,
( int ) nprops , nprops - ( FT_ULong ) ( int ) nprops ) ) ;
nprops = ( FT_ULong ) ( int ) nprops ;
FT_TRACE4 ( ( " number of properties: %ld \n " , orig_nprops ) ) ;
/* rough estimate */
if ( nprops > size / PCF_PROPERTY_SIZE )
if ( orig_nprops > size / PCF_PROPERTY_SIZE )
{
error = FT_THROW ( Invalid_Table ) ;
goto Bail ;
}
/* as a heuristic limit to avoid excessive allocation in */
/* gzip bombs (i.e., very small, invalid input data that */
/* pretends to expand to an insanely large file) we only */
/* load the first 256 properties */
if ( orig_nprops > 256 )
{
FT_TRACE0 ( ( " pcf_get_properties: "
" only loading first 256 properties \n " ) ) ;
nprops = 256 ;
}
else
nprops = orig_nprops ;
face - > nprops = ( int ) nprops ;
if ( FT_NEW_ARRAY ( props , nprops ) )
@ -531,14 +558,23 @@ THE SOFTWARE.
}
}
/* this skip will only work if we really have an extremely large */
/* number of properties; it will fail for fake data, avoiding an */
/* unnecessarily large allocation later on */
if ( FT_STREAM_SKIP ( ( orig_nprops - nprops ) * PCF_PROPERTY_SIZE ) )
{
error = FT_THROW ( Invalid_Stream_Skip ) ;
goto Bail ;
}
/* pad the property array */
/* */
/* clever here - nprops is the same as the number of odd-units read, */
/* as only isStringProp are odd length (Keith Packard) */
/* */
if ( nprops & 3 )
if ( orig_ nprops & 3 )
{
i = 4 - ( nprops & 3 ) ;
i = 4 - ( orig_ nprops & 3 ) ;
if ( FT_STREAM_SKIP ( i ) )
{
error = FT_THROW ( Invalid_Stream_Skip ) ;
@ -553,15 +589,24 @@ THE SOFTWARE.
if ( error )
goto Bail ;
FT_TRACE4 ( ( " string_size = %ld \n " , string_size ) ) ;
FT_TRACE4 ( ( " string size: %ld \n " , string_size ) ) ;
/* rough estimate */
if ( string_size > size - nprops * PCF_PROPERTY_SIZE )
if ( string_size > size - orig_ nprops * PCF_PROPERTY_SIZE )
{
error = FT_THROW ( Invalid_Table ) ;
goto Bail ;
}
/* the strings in the `strings' array are PostScript strings, */
/* which can have a maximum length of 65536 characters each */
if ( string_size > 16777472 ) /* 256 * (65536 + 1) */
{
FT_TRACE0 ( ( " pcf_get_properties: "
" loading only 16777472 bytes of strings array \n " ) ) ;
string_size = 16777472 ;
}
/* allocate one more byte so that we have a final null byte */
if ( FT_NEW_ARRAY ( strings , string_size + 1 ) )
goto Bail ;
@ -575,6 +620,7 @@ THE SOFTWARE.
face - > properties = properties ;
FT_TRACE4 ( ( " \n " ) ) ;
for ( i = 0 ; i < nprops ; i + + )
{
FT_Long name_offset = props [ i ] . name ;
@ -637,7 +683,7 @@ THE SOFTWARE.
FT_Memory memory = FT_FACE ( face ) - > memory ;
FT_ULong format , size ;
PCF_Metric metrics = NULL ;
FT_ULong nmetrics , i ;
FT_ULong nmetrics , orig_nmetrics , i ;
error = pcf_seek_to_table_type ( stream ,
@ -652,6 +698,13 @@ THE SOFTWARE.
if ( FT_READ_ULONG_LE ( format ) )
goto Bail ;
FT_TRACE4 ( ( " pcf_get_metrics: \n "
" format: 0x%lX (%s, %s) \n " ,
format ,
PCF_BYTE_ORDER ( format ) = = MSBFirst ? " MSB " : " LSB " ,
PCF_FORMAT_MATCH ( format , PCF_COMPRESSED_METRICS ) ?
" compressed " : " uncompressed " ) ) ;
if ( ! PCF_FORMAT_MATCH ( format , PCF_DEFAULT_FORMAT ) & &
! PCF_FORMAT_MATCH ( format , PCF_COMPRESSED_METRICS ) )
return FT_THROW ( Invalid_File_Format ) ;
@ -659,61 +712,70 @@ THE SOFTWARE.
if ( PCF_FORMAT_MATCH ( format , PCF_DEFAULT_FORMAT ) )
{
if ( PCF_BYTE_ORDER ( format ) = = MSBFirst )
( void ) FT_READ_ULONG ( nmetrics ) ;
( void ) FT_READ_ULONG ( orig_ nmetrics ) ;
else
( void ) FT_READ_ULONG_LE ( nmetrics ) ;
( void ) FT_READ_ULONG_LE ( orig_ nmetrics ) ;
}
else
{
if ( PCF_BYTE_ORDER ( format ) = = MSBFirst )
( void ) FT_READ_USHORT ( nmetrics ) ;
( void ) FT_READ_USHORT ( orig_ nmetrics ) ;
else
( void ) FT_READ_USHORT_LE ( nmetrics ) ;
( void ) FT_READ_USHORT_LE ( orig_ nmetrics ) ;
}
if ( error )
return FT_THROW ( Invalid_File_Format ) ;
face - > nmetrics = nmetrics ;
if ( ! nmetrics )
return FT_THROW ( Invalid_Table ) ;
FT_TRACE4 ( ( " pcf_get_metrics: \n " ) ) ;
FT_TRACE4 ( ( " number of metrics: %d \n " , nmetrics ) ) ;
FT_TRACE4 ( ( " number of metrics: %ld \n " , orig_nmetrics ) ) ;
/* rough estimate */
if ( PCF_FORMAT_MATCH ( format , PCF_DEFAULT_FORMAT ) )
{
if ( nmetrics > size / PCF_METRIC_SIZE )
if ( orig_nmetrics > size / PCF_METRIC_SIZE )
return FT_THROW ( Invalid_Table ) ;
}
else
{
if ( nmetrics > size / PCF_COMPRESSED_METRIC_SIZE )
if ( orig_ nmetrics > size / PCF_COMPRESSED_METRIC_SIZE )
return FT_THROW ( Invalid_Table ) ;
}
if ( ! orig_nmetrics )
return FT_THROW ( Invalid_Table ) ;
/* PCF is a format from ancient times; Unicode was in its */
/* infancy, and widely used two-byte character sets for CJK */
/* scripts (Big 5, GB 2312, JIS X 0208, etc.) did have at most */
/* 15000 characters. Even the more exotic CNS 11643 and CCCII */
/* standards, which were essentially three-byte character sets, */
/* provided less then 65536 assigned characters. */
/* */
/* While technically possible to have a larger number of glyphs */
/* in PCF files, we thus limit the number to 65536. */
if ( orig_nmetrics > 65536 )
{
FT_TRACE0 ( ( " pcf_get_metrics: "
" only loading first 65536 metrics \n " ) ) ;
nmetrics = 65536 ;
}
else
nmetrics = orig_nmetrics ;
face - > nmetrics = nmetrics ;
if ( FT_NEW_ARRAY ( face - > metrics , nmetrics ) )
return FT_THROW ( Out_Of_Memory ) ;
return error ;
metrics = face - > metrics ;
FT_TRACE4 ( ( " \n " ) ) ;
for ( i = 0 ; i < nmetrics ; i + + , metrics + + )
{
FT_TRACE5 ( ( " idx %ld: " , i ) ) ;
error = pcf_get_metric ( stream , format , metrics ) ;
metrics - > bits = 0 ;
FT_TRACE5 ( ( " idx %d: width=%d, "
" lsb=%d, rsb=%d, ascent=%d, descent=%d, swidth=%d \n " ,
i ,
metrics - > characterWidth ,
metrics - > leftSideBearing ,
metrics - > rightSideBearing ,
metrics - > ascent ,
metrics - > descent ,
metrics - > attributes ) ) ;
if ( error )
break ;
@ -721,7 +783,7 @@ THE SOFTWARE.
/* compute a glyph's bitmap dimensions, thus setting them to zero in */
/* case of an error disables this particular glyph only */
if ( metrics - > rightSideBearing < metrics - > leftSideBearing | |
metrics - > ascent + metrics - > descent < 0 )
metrics - > ascent < - metrics - > descent )
{
metrics - > characterWidth = 0 ;
metrics - > leftSideBearing = 0 ;
@ -751,7 +813,7 @@ THE SOFTWARE.
FT_Long * offsets = NULL ;
FT_Long bitmapSizes [ GLYPHPADOPTIONS ] ;
FT_ULong format , size ;
FT_ULong nbitmaps , i , sizebitmaps = 0 ;
FT_ULong nbitmaps , orig_nbitmaps , i , sizebitmaps = 0 ;
error = pcf_seek_to_table_type ( stream ,
@ -769,18 +831,40 @@ THE SOFTWARE.
format = FT_GET_ULONG_LE ( ) ;
if ( PCF_BYTE_ORDER ( format ) = = MSBFirst )
nbitmaps = FT_GET_ULONG ( ) ;
orig_ nbitmaps = FT_GET_ULONG ( ) ;
else
nbitmaps = FT_GET_ULONG_LE ( ) ;
orig_ nbitmaps = FT_GET_ULONG_LE ( ) ;
FT_Stream_ExitFrame ( stream ) ;
FT_TRACE4 ( ( " pcf_get_bitmaps: \n "
" format: 0x%lX \n "
" (%s, %s, \n "
" padding=%d bits, scanning=%d bits) \n " ,
format ,
PCF_BYTE_ORDER ( format ) = = MSBFirst
? " most significant byte first "
: " least significant byte first " ,
PCF_BIT_ORDER ( format ) = = MSBFirst
? " most significant bit first "
: " least significant bit first " ,
8 < < PCF_GLYPH_PAD_INDEX ( format ) ,
8 < < PCF_SCAN_UNIT_INDEX ( format ) ) ) ;
if ( ! PCF_FORMAT_MATCH ( format , PCF_DEFAULT_FORMAT ) )
return FT_THROW ( Invalid_File_Format ) ;
FT_TRACE4 ( ( " pcf_get_bitmaps: \n " ) ) ;
FT_TRACE4 ( ( " number of bitmaps: %ld \n " , orig_nbitmaps ) ) ;
FT_TRACE4 ( ( " number of bitmaps: %d \n " , nbitmaps ) ) ;
/* see comment in `pcf_get_metrics' */
if ( orig_nbitmaps > 65536 )
{
FT_TRACE0 ( ( " pcf_get_bitmaps: "
" only loading first 65536 bitmaps \n " ) ) ;
nbitmaps = 65536 ;
}
else
nbitmaps = orig_nbitmaps ;
if ( nbitmaps ! = face - > nmetrics )
return FT_THROW ( Invalid_File_Format ) ;
@ -788,6 +872,7 @@ THE SOFTWARE.
if ( FT_NEW_ARRAY ( offsets , nbitmaps ) )
return error ;
FT_TRACE5 ( ( " \n " ) ) ;
for ( i = 0 ; i < nbitmaps ; i + + )
{
if ( PCF_BYTE_ORDER ( format ) = = MSBFirst )
@ -795,7 +880,7 @@ THE SOFTWARE.
else
( void ) FT_READ_LONG_LE ( offsets [ i ] ) ;
FT_TRACE5 ( ( " bitmap %d: offset %ld (0x%lX) \n " ,
FT_TRACE5 ( ( " bitmap %l d: offset %ld (0x%lX) \n " ,
i , offsets [ i ] , offsets [ i ] ) ) ;
}
if ( error )
@ -812,17 +897,19 @@ THE SOFTWARE.
sizebitmaps = ( FT_ULong ) bitmapSizes [ PCF_GLYPH_PAD_INDEX ( format ) ] ;
FT_TRACE4 ( ( " padding %d implies a size of %ld \n " ,
i , bitmapSizes [ i ] ) ) ;
FT_TRACE4 ( ( " %ld-bit padding implies a size of %ld \n " ,
8 < < i , bitmapSizes [ i ] ) ) ;
}
FT_TRACE4 ( ( " %d bitmaps, padding index %ld \n " ,
FT_TRACE4 ( ( " %l d bitmaps, using %ld-bit padding \n " ,
nbitmaps ,
PCF_GLYPH_PAD_INDEX ( format ) ) ) ;
FT_TRACE4 ( ( " bitmap size = % d \n " , sizebitmaps ) ) ;
8 < < PCF_GLYPH_PAD_INDEX ( format ) ) ) ;
FT_TRACE4 ( ( " bitmap size: %l d \n " , sizebitmaps ) ) ;
FT_UNUSED ( sizebitmaps ) ; /* only used for debugging */
/* right now, we only check the bitmap offsets; */
/* actual bitmaps are only loaded on demand */
for ( i = 0 ; i < nbitmaps ; i + + )
{
/* rough estimate */
@ -830,7 +917,7 @@ THE SOFTWARE.
( ( FT_ULong ) offsets [ i ] > size ) )
{
FT_TRACE0 ( ( " pcf_get_bitmaps: "
" invalid offset to bitmap data of glyph %d \n " , i ) ) ;
" invalid offset to bitmap data of glyph %l d \n " , i ) ) ;
}
else
face - > metrics [ i ] . bits = stream - > pos + ( FT_ULong ) offsets [ i ] ;
@ -894,10 +981,20 @@ THE SOFTWARE.
FT_Stream_ExitFrame ( stream ) ;
FT_TRACE4 ( ( " pcf_get_encodings: \n "
" format: 0x%lX (%s) \n " ,
format ,
PCF_BYTE_ORDER ( format ) = = MSBFirst ? " MSB " : " LSB " ) ) ;
if ( ! PCF_FORMAT_MATCH ( format , PCF_DEFAULT_FORMAT ) )
return FT_THROW ( Invalid_File_Format ) ;
/* sanity checks */
FT_TRACE4 ( ( " firstCol 0x%X, lastCol 0x%X \n "
" firstRow 0x%X, lastRow 0x%X \n " ,
firstCol , lastCol ,
firstRow , lastRow ) ) ;
/* sanity checks; we limit numbers of rows and columns to 256 */
if ( firstCol < 0 | |
firstCol > lastCol | |
lastCol > 0xFF | |
@ -906,21 +1003,18 @@ THE SOFTWARE.
lastRow > 0xFF )
return FT_THROW ( Invalid_Table ) ;
FT_TRACE4 ( ( " pdf_get_encodings: \n " ) ) ;
FT_TRACE4 ( ( " firstCol %d, lastCol %d, firstRow %d, lastRow %d \n " ,
firstCol , lastCol , firstRow , lastRow ) ) ;
nencoding = ( FT_ULong ) ( lastCol - firstCol + 1 ) *
( FT_ULong ) ( lastRow - firstRow + 1 ) ;
if ( FT_NEW_ARRAY ( encoding , nencoding ) )
return FT_THROW ( Out_Of_Memory ) ;
return error ;
error = FT_Stream_EnterFrame ( stream , 2 * nencoding ) ;
if ( error )
goto Bail ;
FT_TRACE5 ( ( " \n " ) ) ;
k = 0 ;
for ( i = firstRow ; i < = lastRow ; i + + )
{
@ -1029,6 +1123,15 @@ THE SOFTWARE.
if ( FT_READ_ULONG_LE ( format ) )
goto Bail ;
FT_TRACE4 ( ( " pcf_get_accel%s: \n "
" format: 0x%lX (%s, %s) \n " ,
type = = PCF_BDF_ACCELERATORS ? " (getting BDF accelerators) "
: " " ,
format ,
PCF_BYTE_ORDER ( format ) = = MSBFirst ? " MSB " : " LSB " ,
PCF_FORMAT_MATCH ( format , PCF_ACCEL_W_INKBOUNDS ) ?
" accelerated " : " not accelerated " ) ) ;
if ( ! PCF_FORMAT_MATCH ( format , PCF_DEFAULT_FORMAT ) & &
! PCF_FORMAT_MATCH ( format , PCF_ACCEL_W_INKBOUNDS ) )
goto Bail ;
@ -1044,12 +1147,29 @@ THE SOFTWARE.
goto Bail ;
}
FT_TRACE5 ( ( " noOverlap=%s, constantMetrics=%s, "
" terminalFont=%s, constantWidth=%s \n "
" inkInside=%s, inkMetrics=%s, drawDirection=%s \n "
" fontAscent=%ld, fontDescent=%ld, maxOverlap=%ld \n " ,
accel - > noOverlap ? " yes " : " no " ,
accel - > constantMetrics ? " yes " : " no " ,
accel - > terminalFont ? " yes " : " no " ,
accel - > constantWidth ? " yes " : " no " ,
accel - > inkInside ? " yes " : " no " ,
accel - > inkMetrics ? " yes " : " no " ,
accel - > drawDirection ? " RTL " : " LTR " ,
accel - > fontAscent ,
accel - > fontDescent ,
accel - > maxOverlap ) ) ;
FT_TRACE5 ( ( " minbounds: " ) ) ;
error = pcf_get_metric ( stream ,
format & ( ~ PCF_FORMAT_MASK ) ,
& ( accel - > minbounds ) ) ;
if ( error )
goto Bail ;
FT_TRACE5 ( ( " maxbounds: " ) ) ;
error = pcf_get_metric ( stream ,
format & ( ~ PCF_FORMAT_MASK ) ,
& ( accel - > maxbounds ) ) ;
@ -1058,12 +1178,14 @@ THE SOFTWARE.
if ( PCF_FORMAT_MATCH ( format , PCF_ACCEL_W_INKBOUNDS ) )
{
FT_TRACE5 ( ( " ink minbounds: " ) ) ;
error = pcf_get_metric ( stream ,
format & ( ~ PCF_FORMAT_MASK ) ,
& ( accel - > ink_minbounds ) ) ;
if ( error )
goto Bail ;
FT_TRACE5 ( ( " ink maxbounds: " ) ) ;
error = pcf_get_metric ( stream ,
format & ( ~ PCF_FORMAT_MASK ) ,
& ( accel - > ink_maxbounds ) ) ;
@ -1072,7 +1194,7 @@ THE SOFTWARE.
}
else
{
accel - > ink_minbounds = accel - > minbounds ; /* I'm not sure about this */
accel - > ink_minbounds = accel - > minbounds ;
accel - > ink_maxbounds = accel - > maxbounds ;
}