summaryrefslogtreecommitdiff
path: root/src/pfr/pfrsbit.c
diff options
context:
space:
mode:
authorWerner Lemberg <wl@gnu.org>2016-03-26 08:00:07 +0100
committerWerner Lemberg <wl@gnu.org>2016-03-26 22:42:13 +0100
commitb069a590a9c9e6f06f4d1d5c16df732bd6483536 (patch)
tree3352c68cfb069f2ec2bee07107ed069772e1af4e /src/pfr/pfrsbit.c
parent0003cb916224aa7d12b4cf4c619631ea8932b878 (diff)
downloadfreetype2-b069a590a9c9e6f06f4d1d5c16df732bd6483536.tar.gz
[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.
Diffstat (limited to 'src/pfr/pfrsbit.c')
-rw-r--r--src/pfr/pfrsbit.c71
1 files changed, 59 insertions, 12 deletions
diff --git a/src/pfr/pfrsbit.c b/src/pfr/pfrsbit.c
index 9bc5d41d1..d2715937f 100644
--- a/src/pfr/pfrsbit.c
+++ b/src/pfr/pfrsbit.c
@@ -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 );