[pfr] Robustify bitmap strike handling (#47514).

We did a binary search for a charcode without ensuring that the
searched data is ordered.  Validating the order is now done lazily,
this is, the first access to a bitmap glyph triggers the order check
in the corresponding bitmap strike.

* src/pfr/pfrtypes.h (PFR_BitmapFlags): New values
`PFR_BITMAP_VALID_CHARCODES' and `PFR_BITMAP_CHARCODES_VALIDATED'.

* src/pfr/pfrsbit.c (pfr_lookup_bitmap_data): Make `flags' argument
a pointer.  Handle new PFR_BITMAP_XXX flags.
(pfr_slot_load_bitmap): Updated.
This commit is contained in:
Werner Lemberg 2016-03-26 08:00:07 +01:00
parent 0003cb9162
commit b069a590a9
3 changed files with 80 additions and 13 deletions

View File

@ -1,4 +1,20 @@
2016-03-25 Werner Lemberg <wl@gnu.org>
2016-03-26 Werner Lemberg <wl@gnu.org>
[pfr] Robustify bitmap strike handling (#47514).
We did a binary search for a charcode without ensuring that the
searched data is ordered. Validating the order is now done lazily,
this is, the first access to a bitmap glyph triggers the order check
in the corresponding bitmap strike.
* src/pfr/pfrtypes.h (PFR_BitmapFlags): New values
`PFR_BITMAP_VALID_CHARCODES' and `PFR_BITMAP_CHARCODES_VALIDATED'.
* src/pfr/pfrsbit.c (pfr_lookup_bitmap_data): Make `flags' argument
a pointer. Handle new PFR_BITMAP_XXX flags.
(pfr_slot_load_bitmap): Updated.
2016-03-26 Werner Lemberg <wl@gnu.org>
[pfr] Fix handling of compound glyphs.

View File

@ -277,24 +277,76 @@
pfr_lookup_bitmap_data( FT_Byte* base,
FT_Byte* limit,
FT_UInt count,
FT_UInt flags,
FT_UInt* flags,
FT_UInt char_code,
FT_ULong* found_offset,
FT_ULong* found_size )
{
FT_UInt left, right, char_len;
FT_Bool two = FT_BOOL( flags & PFR_BITMAP_2BYTE_CHARCODE );
FT_Bool two = FT_BOOL( *flags & PFR_BITMAP_2BYTE_CHARCODE );
FT_Byte* buff;
char_len = 4;
if ( two )
char_len += 1;
if ( flags & PFR_BITMAP_2BYTE_SIZE )
if ( *flags & PFR_BITMAP_2BYTE_SIZE )
char_len += 1;
if ( flags & PFR_BITMAP_3BYTE_OFFSET )
if ( *flags & PFR_BITMAP_3BYTE_OFFSET )
char_len += 1;
if ( !( *flags & PFR_BITMAP_CHARCODES_VALIDATED ) )
{
FT_Byte* p;
FT_Byte* lim;
FT_UInt code;
FT_Long prev_code;
*flags |= PFR_BITMAP_VALID_CHARCODES;
prev_code = -1;
lim = base + count * char_len;
if ( lim > limit )
{
FT_TRACE0(( "pfr_lookup_bitmap_data:"
" number of bitmap records too large,\n"
" "
" thus ignoring all bitmaps in this strike\n" ));
*flags &= ~PFR_BITMAP_VALID_CHARCODES;
}
else
{
/* check whether records are sorted by code */
for ( p = base; p < lim; p += char_len )
{
if ( two )
code = FT_PEEK_USHORT( p );
else
code = *p;
if ( code <= prev_code )
{
FT_TRACE0(( "pfr_lookup_bitmap_data:"
" bitmap records are not sorted,\n"
" "
" thus ignoring all bitmaps in this strike\n" ));
*flags &= ~PFR_BITMAP_VALID_CHARCODES;
break;
}
prev_code = code;
}
}
*flags |= PFR_BITMAP_CHARCODES_VALIDATED;
}
/* ignore bitmaps in case table is not valid */
/* (this might be sanitized, but PFR is dead...) */
if ( !( *flags & PFR_BITMAP_VALID_CHARCODES ) )
goto Fail;
left = 0;
right = count;
@ -306,11 +358,6 @@
middle = ( left + right ) >> 1;
buff = base + middle * char_len;
/* check that we are not outside of the table -- */
/* this is possible with broken fonts... */
if ( buff + char_len > limit )
goto Fail;
if ( two )
code = PFR_NEXT_USHORT( buff );
else
@ -332,12 +379,12 @@
return;
Found_It:
if ( flags & PFR_BITMAP_2BYTE_SIZE )
if ( *flags & PFR_BITMAP_2BYTE_SIZE )
*found_size = PFR_NEXT_USHORT( buff );
else
*found_size = PFR_NEXT_BYTE( buff );
if ( flags & PFR_BITMAP_3BYTE_OFFSET )
if ( *flags & PFR_BITMAP_3BYTE_OFFSET )
*found_offset = PFR_NEXT_ULONG( buff );
else
*found_offset = PFR_NEXT_USHORT( buff );
@ -588,7 +635,7 @@
pfr_lookup_bitmap_data( stream->cursor,
stream->limit,
strike->num_bitmaps,
strike->flags,
&strike->flags,
character->char_code,
&gps_offset,
&gps_size );

View File

@ -121,6 +121,10 @@ FT_BEGIN_HEADER
typedef enum PFR_BitmapFlags_
{
/* not part of the specification but used for implementation */
PFR_BITMAP_VALID_CHARCODES = 0x80,
PFR_BITMAP_CHARCODES_VALIDATED = 0x40,
PFR_BITMAP_3BYTE_OFFSET = 4,
PFR_BITMAP_2BYTE_SIZE = 2,
PFR_BITMAP_2BYTE_CHARCODE = 1