[pcf] Revise driver.

This commit improves tracing and handling of malformed fonts.  In
particular, the changes to `pcf_get_properties' fix

  https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=379

* src/pcf/pcfread.c (tableNames): Use long names for better
readability.
(pcf_read_TOC): Allow at most 9 tables.
(pcf_get_properties): Allow at most 256 properties.
Limit strings array length to 256 * (65536 + 1) bytes.
Better tracing.
(pcf_get_metric): Trace metric data.
(pcf_get_metrics): Allow at most 65536 metrics.
Fix comparison of `metrics->ascent' and `metrics->descent' to avoid
potential overflow.
Better tracing.
(pcf_get_bitmaps): Allow at most 65536 bitmaps.
Better tracing.
(pcf_get_encodings, pcf_get_accel): Better tracing.

* src/pcf/pcfdrivr.c (PCF_Glyph_Load): Don't trace `format' details.
These are now shown by `pcf_get_bitmaps'.
This commit is contained in:
Werner Lemberg 2017-01-06 11:47:55 +01:00
parent 348d39c68a
commit 8b755445bb
3 changed files with 236 additions and 88 deletions

View File

@ -1,3 +1,30 @@
2017-01-06 Werner Lemberg <wl@gnu.org>
[pcf] Revise driver.
This commit improves tracing and handling of malformed fonts. In
particular, the changes to `pcf_get_properties' fix
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=379
* src/pcf/pcfread.c (tableNames): Use long names for better
readability.
(pcf_read_TOC): Allow at most 9 tables.
(pcf_get_properties): Allow at most 256 properties.
Limit strings array length to 256 * (65536 + 1) bytes.
Better tracing.
(pcf_get_metric): Trace metric data.
(pcf_get_metrics): Allow at most 65536 metrics.
Fix comparison of `metrics->ascent' and `metrics->descent' to avoid
potential overflow.
Better tracing.
(pcf_get_bitmaps): Allow at most 65536 bitmaps.
Better tracing.
(pcf_get_encodings, pcf_get_accel): Better tracing.
* src/pcf/pcfdrivr.c (PCF_Glyph_Load): Don't trace `format' details.
These are now shown by `pcf_get_bitmaps'.
2017-01-04 Werner Lemberg <wl@gnu.org> 2017-01-04 Werner Lemberg <wl@gnu.org>
* src/pcf/pcfdrivr.c (PCF_Face_Init): Trace compression format. * src/pcf/pcfdrivr.c (PCF_Face_Init): Trace compression format.

View File

@ -524,11 +524,6 @@ THE SOFTWARE.
bitmap->num_grays = 1; bitmap->num_grays = 1;
bitmap->pixel_mode = FT_PIXEL_MODE_MONO; bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
FT_TRACE6(( "BIT_ORDER %d ; BYTE_ORDER %d ; GLYPH_PAD %d\n",
PCF_BIT_ORDER( face->bitmapsFormat ),
PCF_BYTE_ORDER( face->bitmapsFormat ),
PCF_GLYPH_PAD( face->bitmapsFormat ) ));
switch ( PCF_GLYPH_PAD( face->bitmapsFormat ) ) switch ( PCF_GLYPH_PAD( face->bitmapsFormat ) )
{ {
case 1: case 1:
@ -630,19 +625,23 @@ THE SOFTWARE.
} }
else else
{ {
if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) ) if ( prop->value.l > 0x7FFFFFFFL ||
prop->value.l < ( -1 - 0x7FFFFFFFL ) )
{ {
FT_TRACE1(( "pcf_get_bdf_property: " )); FT_TRACE1(( "pcf_get_bdf_property:" ));
FT_TRACE1(( "too large integer 0x%x is truncated\n" )); FT_TRACE1(( " too large integer 0x%x is truncated\n" ));
} }
/* Apparently, the PCF driver loads all properties as signed integers!
* This really doesn't seem to be a problem, because this is /*
* sufficient for any meaningful values. * The PCF driver loads all properties as signed integers.
* This really doesn't seem to be a problem, because this is
* sufficient for any meaningful values.
*/ */
aproperty->type = BDF_PROPERTY_TYPE_INTEGER; aproperty->type = BDF_PROPERTY_TYPE_INTEGER;
aproperty->u.integer = (FT_Int32)prop->value.l; aproperty->u.integer = (FT_Int32)prop->value.l;
} }
return 0;
return FT_Err_Ok;
} }
return FT_THROW( Invalid_Argument ); return FT_THROW( Invalid_Argument );
@ -657,7 +656,7 @@ THE SOFTWARE.
*acharset_encoding = face->charset_encoding; *acharset_encoding = face->charset_encoding;
*acharset_registry = face->charset_registry; *acharset_registry = face->charset_registry;
return 0; return FT_Err_Ok;
} }

View File

@ -50,8 +50,15 @@ THE SOFTWARE.
#ifdef FT_DEBUG_LEVEL_TRACE #ifdef FT_DEBUG_LEVEL_TRACE
static const char* const tableNames[] = static const char* const tableNames[] =
{ {
"prop", "accl", "mtrcs", "bmps", "imtrcs", "properties",
"enc", "swidth", "names", "accel" "accelerators",
"metrics",
"bitmaps",
"ink metrics",
"encodings",
"swidths",
"glyph names",
"BDF accelerators"
}; };
#endif #endif
@ -109,22 +116,20 @@ THE SOFTWARE.
if ( stream->size < 16 ) if ( stream->size < 16 )
return FT_THROW( Invalid_File_Format ); return FT_THROW( Invalid_File_Format );
/* We need 16 bytes per TOC entry. Additionally, as a */ /* we need 16 bytes per TOC entry, */
/* heuristic protection against gzip bombs (i.e., very */ /* and there can be most 9 tables */
/* small input files that expand to insanely large */ if ( toc->count > ( stream->size >> 4 ) ||
/* files), we limit the number of TOC entries to 1024. */ toc->count > 9 )
if ( toc->count > stream->size >> 4 ||
toc->count > 1024 )
{ {
FT_TRACE0(( "pcf_read_TOC: adjusting number of tables" FT_TRACE0(( "pcf_read_TOC: adjusting number of tables"
" (from %d to %d)\n", " (from %d to %d)\n",
toc->count, toc->count,
FT_MIN( stream->size >> 4, 1024 ) )); FT_MIN( stream->size >> 4, 9 ) ));
toc->count = FT_MIN( stream->size >> 4, 1024 ); toc->count = FT_MIN( stream->size >> 4, 9 );
} }
if ( FT_NEW_ARRAY( face->toc.tables, toc->count ) ) if ( FT_NEW_ARRAY( face->toc.tables, toc->count ) )
return FT_THROW( Out_Of_Memory ); return error;
tables = face->toc.tables; tables = face->toc.tables;
for ( n = 0; n < toc->count; n++ ) for ( n = 0; n < toc->count; n++ )
@ -237,8 +242,8 @@ THE SOFTWARE.
if ( tables[i].type == (FT_UInt)( 1 << j ) ) if ( tables[i].type == (FT_UInt)( 1 << j ) )
name = tableNames[j]; name = tableNames[j];
FT_TRACE4(( " %d: type=%s, format=0x%X, " FT_TRACE4(( " %d: type=%s, format=0x%X,"
"size=%ld (0x%lX), offset=%ld (0x%lX)\n", " size=%ld (0x%lX), offset=%ld (0x%lX)\n",
i, name, i, name,
tables[i].format, tables[i].format,
tables[i].size, tables[i].size, tables[i].size, tables[i].size,
@ -348,6 +353,17 @@ THE SOFTWARE.
metric->attributes = 0; 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: Exit:
return error; return error;
} }
@ -466,7 +482,7 @@ THE SOFTWARE.
{ {
PCF_ParseProperty props = NULL; PCF_ParseProperty props = NULL;
PCF_Property properties = NULL; PCF_Property properties = NULL;
FT_ULong nprops, i; FT_ULong nprops, orig_nprops, i;
FT_ULong format, size; FT_ULong format, size;
FT_Error error; FT_Error error;
FT_Memory memory = FT_FACE( face )->memory; FT_Memory memory = FT_FACE( face )->memory;
@ -486,32 +502,43 @@ THE SOFTWARE.
if ( FT_READ_ULONG_LE( format ) ) if ( FT_READ_ULONG_LE( format ) )
goto Bail; goto Bail;
FT_TRACE4(( "pcf_get_properties:\n" )); FT_TRACE4(( "pcf_get_properties:\n"
" format: 0x%lX (%s)\n",
FT_TRACE4(( " format = %ld\n", format )); format,
PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB" ));
if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
goto Bail; goto Bail;
if ( PCF_BYTE_ORDER( format ) == MSBFirst ) if ( PCF_BYTE_ORDER( format ) == MSBFirst )
(void)FT_READ_ULONG( nprops ); (void)FT_READ_ULONG( orig_nprops );
else else
(void)FT_READ_ULONG_LE( nprops ); (void)FT_READ_ULONG_LE( orig_nprops );
if ( error ) if ( error )
goto Bail; goto Bail;
FT_TRACE4(( " nprop = %d (truncate %d props)\n", FT_TRACE4(( " number of properties: %ld\n", orig_nprops ));
(int)nprops, nprops - (FT_ULong)(int)nprops ));
nprops = (FT_ULong)(int)nprops;
/* rough estimate */ /* rough estimate */
if ( nprops > size / PCF_PROPERTY_SIZE ) if ( orig_nprops > size / PCF_PROPERTY_SIZE )
{ {
error = FT_THROW( Invalid_Table ); error = FT_THROW( Invalid_Table );
goto Bail; 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; face->nprops = (int)nprops;
if ( FT_NEW_ARRAY( props, 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 */ /* pad the property array */
/* */ /* */
/* clever here - nprops is the same as the number of odd-units read, */ /* clever here - nprops is the same as the number of odd-units read, */
/* as only isStringProp are odd length (Keith Packard) */ /* 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 ) ) if ( FT_STREAM_SKIP( i ) )
{ {
error = FT_THROW( Invalid_Stream_Skip ); error = FT_THROW( Invalid_Stream_Skip );
@ -553,15 +589,24 @@ THE SOFTWARE.
if ( error ) if ( error )
goto Bail; goto Bail;
FT_TRACE4(( " string_size = %ld\n", string_size )); FT_TRACE4(( " string size: %ld\n", string_size ));
/* rough estimate */ /* rough estimate */
if ( string_size > size - nprops * PCF_PROPERTY_SIZE ) if ( string_size > size - orig_nprops * PCF_PROPERTY_SIZE )
{ {
error = FT_THROW( Invalid_Table ); error = FT_THROW( Invalid_Table );
goto Bail; 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 */ /* allocate one more byte so that we have a final null byte */
if ( FT_NEW_ARRAY( strings, string_size + 1 ) ) if ( FT_NEW_ARRAY( strings, string_size + 1 ) )
goto Bail; goto Bail;
@ -575,6 +620,7 @@ THE SOFTWARE.
face->properties = properties; face->properties = properties;
FT_TRACE4(( "\n" ));
for ( i = 0; i < nprops; i++ ) for ( i = 0; i < nprops; i++ )
{ {
FT_Long name_offset = props[i].name; FT_Long name_offset = props[i].name;
@ -637,7 +683,7 @@ THE SOFTWARE.
FT_Memory memory = FT_FACE( face )->memory; FT_Memory memory = FT_FACE( face )->memory;
FT_ULong format, size; FT_ULong format, size;
PCF_Metric metrics = NULL; PCF_Metric metrics = NULL;
FT_ULong nmetrics, i; FT_ULong nmetrics, orig_nmetrics, i;
error = pcf_seek_to_table_type( stream, error = pcf_seek_to_table_type( stream,
@ -652,6 +698,13 @@ THE SOFTWARE.
if ( FT_READ_ULONG_LE( format ) ) if ( FT_READ_ULONG_LE( format ) )
goto Bail; 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 ) && if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) &&
!PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) ) !PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) )
return FT_THROW( Invalid_File_Format ); return FT_THROW( Invalid_File_Format );
@ -659,61 +712,70 @@ THE SOFTWARE.
if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
{ {
if ( PCF_BYTE_ORDER( format ) == MSBFirst ) if ( PCF_BYTE_ORDER( format ) == MSBFirst )
(void)FT_READ_ULONG( nmetrics ); (void)FT_READ_ULONG( orig_nmetrics );
else else
(void)FT_READ_ULONG_LE( nmetrics ); (void)FT_READ_ULONG_LE( orig_nmetrics );
} }
else else
{ {
if ( PCF_BYTE_ORDER( format ) == MSBFirst ) if ( PCF_BYTE_ORDER( format ) == MSBFirst )
(void)FT_READ_USHORT( nmetrics ); (void)FT_READ_USHORT( orig_nmetrics );
else else
(void)FT_READ_USHORT_LE( nmetrics ); (void)FT_READ_USHORT_LE( orig_nmetrics );
} }
if ( error ) if ( error )
return FT_THROW( Invalid_File_Format ); return FT_THROW( Invalid_File_Format );
face->nmetrics = nmetrics; FT_TRACE4(( " number of metrics: %ld\n", orig_nmetrics ));
if ( !nmetrics )
return FT_THROW( Invalid_Table );
FT_TRACE4(( "pcf_get_metrics:\n" ));
FT_TRACE4(( " number of metrics: %d\n", nmetrics ));
/* rough estimate */ /* rough estimate */
if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) 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 ); return FT_THROW( Invalid_Table );
} }
else else
{ {
if ( nmetrics > size / PCF_COMPRESSED_METRIC_SIZE ) if ( orig_nmetrics > size / PCF_COMPRESSED_METRIC_SIZE )
return FT_THROW( Invalid_Table ); 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 ) ) if ( FT_NEW_ARRAY( face->metrics, nmetrics ) )
return FT_THROW( Out_Of_Memory ); return error;
metrics = face->metrics; metrics = face->metrics;
FT_TRACE4(( "\n" ));
for ( i = 0; i < nmetrics; i++, metrics++ ) for ( i = 0; i < nmetrics; i++, metrics++ )
{ {
FT_TRACE5(( " idx %ld:", i ));
error = pcf_get_metric( stream, format, metrics ); error = pcf_get_metric( stream, format, metrics );
metrics->bits = 0; 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 ) if ( error )
break; break;
@ -721,7 +783,7 @@ THE SOFTWARE.
/* compute a glyph's bitmap dimensions, thus setting them to zero in */ /* compute a glyph's bitmap dimensions, thus setting them to zero in */
/* case of an error disables this particular glyph only */ /* case of an error disables this particular glyph only */
if ( metrics->rightSideBearing < metrics->leftSideBearing || if ( metrics->rightSideBearing < metrics->leftSideBearing ||
metrics->ascent + metrics->descent < 0 ) metrics->ascent < -metrics->descent )
{ {
metrics->characterWidth = 0; metrics->characterWidth = 0;
metrics->leftSideBearing = 0; metrics->leftSideBearing = 0;
@ -751,7 +813,7 @@ THE SOFTWARE.
FT_Long* offsets = NULL; FT_Long* offsets = NULL;
FT_Long bitmapSizes[GLYPHPADOPTIONS]; FT_Long bitmapSizes[GLYPHPADOPTIONS];
FT_ULong format, size; 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, error = pcf_seek_to_table_type( stream,
@ -769,18 +831,40 @@ THE SOFTWARE.
format = FT_GET_ULONG_LE(); format = FT_GET_ULONG_LE();
if ( PCF_BYTE_ORDER( format ) == MSBFirst ) if ( PCF_BYTE_ORDER( format ) == MSBFirst )
nbitmaps = FT_GET_ULONG(); orig_nbitmaps = FT_GET_ULONG();
else else
nbitmaps = FT_GET_ULONG_LE(); orig_nbitmaps = FT_GET_ULONG_LE();
FT_Stream_ExitFrame( stream ); 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 ) ) if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
return FT_THROW( Invalid_File_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 ) if ( nbitmaps != face->nmetrics )
return FT_THROW( Invalid_File_Format ); return FT_THROW( Invalid_File_Format );
@ -788,6 +872,7 @@ THE SOFTWARE.
if ( FT_NEW_ARRAY( offsets, nbitmaps ) ) if ( FT_NEW_ARRAY( offsets, nbitmaps ) )
return error; return error;
FT_TRACE5(( "\n" ));
for ( i = 0; i < nbitmaps; i++ ) for ( i = 0; i < nbitmaps; i++ )
{ {
if ( PCF_BYTE_ORDER( format ) == MSBFirst ) if ( PCF_BYTE_ORDER( format ) == MSBFirst )
@ -795,7 +880,7 @@ THE SOFTWARE.
else else
(void)FT_READ_LONG_LE( offsets[i] ); (void)FT_READ_LONG_LE( offsets[i] );
FT_TRACE5(( " bitmap %d: offset %ld (0x%lX)\n", FT_TRACE5(( " bitmap %ld: offset %ld (0x%lX)\n",
i, offsets[i], offsets[i] )); i, offsets[i], offsets[i] ));
} }
if ( error ) if ( error )
@ -812,17 +897,19 @@ THE SOFTWARE.
sizebitmaps = (FT_ULong)bitmapSizes[PCF_GLYPH_PAD_INDEX( format )]; sizebitmaps = (FT_ULong)bitmapSizes[PCF_GLYPH_PAD_INDEX( format )];
FT_TRACE4(( " padding %d implies a size of %ld\n", FT_TRACE4(( " %ld-bit padding implies a size of %ld\n",
i, bitmapSizes[i] )); 8 << i, bitmapSizes[i] ));
} }
FT_TRACE4(( " %d bitmaps, padding index %ld\n", FT_TRACE4(( " %ld bitmaps, using %ld-bit padding\n",
nbitmaps, nbitmaps,
PCF_GLYPH_PAD_INDEX( format ) )); 8 << PCF_GLYPH_PAD_INDEX( format ) ));
FT_TRACE4(( " bitmap size = %d\n", sizebitmaps )); FT_TRACE4(( " bitmap size: %ld\n", sizebitmaps ));
FT_UNUSED( sizebitmaps ); /* only used for debugging */ 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++ ) for ( i = 0; i < nbitmaps; i++ )
{ {
/* rough estimate */ /* rough estimate */
@ -830,7 +917,7 @@ THE SOFTWARE.
( (FT_ULong)offsets[i] > size ) ) ( (FT_ULong)offsets[i] > size ) )
{ {
FT_TRACE0(( "pcf_get_bitmaps:" FT_TRACE0(( "pcf_get_bitmaps:"
" invalid offset to bitmap data of glyph %d\n", i )); " invalid offset to bitmap data of glyph %ld\n", i ));
} }
else else
face->metrics[i].bits = stream->pos + (FT_ULong)offsets[i]; face->metrics[i].bits = stream->pos + (FT_ULong)offsets[i];
@ -894,10 +981,20 @@ THE SOFTWARE.
FT_Stream_ExitFrame( stream ); 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 ) ) if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
return FT_THROW( Invalid_File_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 || if ( firstCol < 0 ||
firstCol > lastCol || firstCol > lastCol ||
lastCol > 0xFF || lastCol > 0xFF ||
@ -906,21 +1003,18 @@ THE SOFTWARE.
lastRow > 0xFF ) lastRow > 0xFF )
return FT_THROW( Invalid_Table ); 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 ) * nencoding = (FT_ULong)( lastCol - firstCol + 1 ) *
(FT_ULong)( lastRow - firstRow + 1 ); (FT_ULong)( lastRow - firstRow + 1 );
if ( FT_NEW_ARRAY( encoding, nencoding ) ) if ( FT_NEW_ARRAY( encoding, nencoding ) )
return FT_THROW( Out_Of_Memory ); return error;
error = FT_Stream_EnterFrame( stream, 2 * nencoding ); error = FT_Stream_EnterFrame( stream, 2 * nencoding );
if ( error ) if ( error )
goto Bail; goto Bail;
FT_TRACE5(( "\n" ));
k = 0; k = 0;
for ( i = firstRow; i <= lastRow; i++ ) for ( i = firstRow; i <= lastRow; i++ )
{ {
@ -1029,6 +1123,15 @@ THE SOFTWARE.
if ( FT_READ_ULONG_LE( format ) ) if ( FT_READ_ULONG_LE( format ) )
goto Bail; 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 ) && if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) &&
!PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) ) !PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
goto Bail; goto Bail;
@ -1044,12 +1147,29 @@ THE SOFTWARE.
goto Bail; 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, error = pcf_get_metric( stream,
format & ( ~PCF_FORMAT_MASK ), format & ( ~PCF_FORMAT_MASK ),
&(accel->minbounds) ); &(accel->minbounds) );
if ( error ) if ( error )
goto Bail; goto Bail;
FT_TRACE5(( " maxbounds:" ));
error = pcf_get_metric( stream, error = pcf_get_metric( stream,
format & ( ~PCF_FORMAT_MASK ), format & ( ~PCF_FORMAT_MASK ),
&(accel->maxbounds) ); &(accel->maxbounds) );
@ -1058,12 +1178,14 @@ THE SOFTWARE.
if ( PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) ) if ( PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
{ {
FT_TRACE5(( " ink minbounds:" ));
error = pcf_get_metric( stream, error = pcf_get_metric( stream,
format & ( ~PCF_FORMAT_MASK ), format & ( ~PCF_FORMAT_MASK ),
&(accel->ink_minbounds) ); &(accel->ink_minbounds) );
if ( error ) if ( error )
goto Bail; goto Bail;
FT_TRACE5(( " ink maxbounds:" ));
error = pcf_get_metric( stream, error = pcf_get_metric( stream,
format & ( ~PCF_FORMAT_MASK ), format & ( ~PCF_FORMAT_MASK ),
&(accel->ink_maxbounds) ); &(accel->ink_maxbounds) );
@ -1072,7 +1194,7 @@ THE SOFTWARE.
} }
else else
{ {
accel->ink_minbounds = accel->minbounds; /* I'm not sure about this */ accel->ink_minbounds = accel->minbounds;
accel->ink_maxbounds = accel->maxbounds; accel->ink_maxbounds = accel->maxbounds;
} }