Fix Savannah bug #25781.

We now simply check for a valid `offset', no longer handling `delta
= 1' specially.

* src/sfnt/ttcmap.c (tt_cmap4_validate): Don't check `delta' for
last segment.
(tt_cmap4_set_range, tt_cmap4_char_map_linear,
tt_cmap4_char_map_binary): Check offset.
This commit is contained in:
Werner Lemberg 2009-03-11 06:47:49 +00:00
parent 34ca21edc6
commit 801e7bae3a
2 changed files with 88 additions and 41 deletions

View File

@ -1,3 +1,14 @@
2009-03-11 Werner Lemberg <wl@gnu.org>
Fix Savannah bug #25781.
We now simply check for a valid `offset', no longer handling `delta
= 1' specially.
* src/sfnt/ttcmap.c (tt_cmap4_validate): Don't check `delta' for
last segment.
(tt_cmap4_set_range, tt_cmap4_char_map_linear,
tt_cmap4_char_map_binary): Check offset.
2009-03-11 Werner Lemberg <wl@gnu.org>
* src/base/Jamfile: Fix handling of ftadvanc.c.

View File

@ -231,7 +231,7 @@
/* language 4 USHORT Mac language code */
/* keys 6 USHORT[256] sub-header keys */
/* subs 518 SUBHEAD[NSUBS] sub-headers array */
/* glyph_ids 518+NSUB*8 USHORT[] glyph id array */
/* glyph_ids 518+NSUB*8 USHORT[] glyph ID array */
/* */
/* The `keys' table is used to map charcode high-bytes to sub-headers. */
/* The value of `NSUBS' is the number of sub-headers defined in the */
@ -282,7 +282,7 @@
FT_UInt n, max_subs;
FT_Byte* keys; /* keys table */
FT_Byte* subs; /* sub-headers */
FT_Byte* glyph_ids; /* glyph id array */
FT_Byte* glyph_ids; /* glyph ID array */
if ( table + length > valid->limit || length < 6 + 512 )
@ -605,14 +605,14 @@
/* each segment; can be */
/* zero */
/* */
/* glyphIds 16+NUM_SEGS*8 USHORT[] array of glyph id */
/* glyphIds 16+NUM_SEGS*8 USHORT[] array of glyph ID */
/* ranges */
/* */
/* Character codes are modelled by a series of ordered (increasing) */
/* intervals called segments. Each segment has start and end codes, */
/* provided by the `startCount' and `endCount' arrays. Segments must */
/* not be overlapping and the last segment should always contain the */
/* `0xFFFF' endCount. */
/* not overlap, and the last segment should always contain the value */
/* 0xFFFF for `endCount'. */
/* */
/* The fields `searchRange', `entrySelector' and `rangeShift' are better */
/* ignored (they are traces of over-engineering in the TrueType */
@ -629,10 +629,10 @@
/* the segment, and the value of `idDelta' is added to it. */
/* */
/* */
/* Finally, note that certain fonts contain invalid charmaps that */
/* contain end=0xFFFF, start=0xFFFF, delta=0x0001, offset=0xFFFF at the */
/* of their charmaps (e.g. opens___.ttf which comes with OpenOffice.org) */
/* we need special code to deal with them correctly... */
/* Finally, note that a lot of fonts contain an invalid last segment, */
/* where `start' and `end' are correctly set to 0xFFFF but both `delta' */
/* and `offset' are incorrect (e.g., `opens___.ttf' which comes with */
/* OpenOffice.org). We need special code to deal with them correctly. */
/* */
#ifdef TT_CONFIG_CMAP_FORMAT_4
@ -697,13 +697,22 @@
p += num_ranges * 2;
offset = FT_PEEK_USHORT( p );
/* some fonts handle the last segment incorrectly; */
/* we have to catch it */
/* some fonts have an incorrect last segment; */
/* we have to catch it */
if ( range_index >= num_ranges - 1 &&
cmap->cur_start == 0xFFFFU &&
cmap->cur_end == 0xFFFFU &&
cmap->cur_delta == 0x1U )
offset = 0;
cmap->cur_end == 0xFFFFU )
{
TT_Face face = (TT_Face)cmap->cmap.cmap.charmap.face;
FT_Byte* limit = face->cmap_table + face->cmap_size;
if ( offset && p + offset + 2 > limit )
{
cmap->cur_delta = 1;
offset = 0;
}
}
if ( offset != 0xFFFFU )
{
@ -870,7 +879,7 @@
offsets = deltas + num_segs * 2;
glyph_ids = offsets + num_segs * 2;
/* check last segment, its end count must be 0xFFFF */
/* check last segment; its end count value must be 0xFFFF */
if ( valid->level >= FT_VALIDATE_PARANOID )
{
p = ends + ( num_segs - 1 ) * 2;
@ -899,10 +908,10 @@
if ( start > end )
FT_INVALID_DATA;
/* this test should be performed at default validation level; */
/* unfortunately, some popular Asian fonts present overlapping */
/* ranges in their charmaps */
/* */
/* this test should be performed at default validation level; */
/* unfortunately, some popular Asian fonts have overlapping */
/* ranges in their charmaps */
/* */
if ( start <= last_end && n > 0 )
{
if ( valid->level >= FT_VALIDATE_TIGHT )
@ -910,7 +919,7 @@
else
{
/* allow overlapping segments, provided their start points */
/* and end points, respectively, are in ascending order. */
/* and end points, respectively, are in ascending order */
/* */
if ( last_start > start || last_end > end )
error |= TT_CMAP_FLAG_UNSORTED;
@ -921,7 +930,7 @@
if ( offset && offset != 0xFFFFU )
{
p += offset; /* start of glyph id array */
p += offset; /* start of glyph ID array */
/* check that we point within the glyph IDs table only */
if ( valid->level >= FT_VALIDATE_TIGHT )
@ -930,11 +939,18 @@
p + ( end - start + 1 ) * 2 > table + length )
FT_INVALID_DATA;
}
/* some fonts handle the last segment incorrectly */
else if ( n != num_segs - 1 ||
!( start == 0xFFFFU &&
end == 0xFFFFU &&
delta == 0x1U ) )
/* Some fonts handle the last segment incorrectly. In */
/* theory, 0xFFFF might point to an ordinary glyph -- */
/* a cmap 4 is versatile and could be used for any */
/* encoding, not only Unicode. However, reality shows */
/* that far too many fonts are sloppy and incorrectly */
/* set all fields but `start' and `end' for the last */
/* segment if it contains only a single character. */
/* */
/* We thus omit the test here, delaying it to the */
/* routines which actually access the cmap. */
else if ( n != num_segs - 1 ||
!( start == 0xFFFFU && end == 0xFFFFU ) )
{
if ( p < glyph_ids ||
p + ( end - start + 1 ) * 2 > valid->limit )
@ -965,9 +981,9 @@
/* some fonts (erroneously?) use a range offset of 0xFFFF */
/* to mean missing glyph in cmap table */
/* */
if ( valid->level >= FT_VALIDATE_PARANOID ||
n != num_segs - 1 ||
!( start == 0xFFFFU && end == 0xFFFFU && delta == 0x1U ) )
if ( valid->level >= FT_VALIDATE_PARANOID ||
n != num_segs - 1 ||
!( start == 0xFFFFU && end == 0xFFFFU ) )
FT_INVALID_DATA;
}
@ -1025,11 +1041,21 @@
p += num_segs2;
offset = TT_PEEK_USHORT( p );
/* some fonts handle the last segment incorrectly; */
/* we have to catch it */
if ( i >= num_segs - 1 &&
start == 0xFFFFU && end == 0xFFFFU && delta == 0x1U )
offset = 0;
/* some fonts have an incorrect last segment; */
/* we have to catch it */
if ( i >= num_segs - 1 &&
start == 0xFFFFU && end == 0xFFFFU )
{
TT_Face face = (TT_Face)cmap->cmap.charmap.face;
FT_Byte* limit = face->cmap_table + face->cmap_size;
if ( offset && p + offset + 2 > limit )
{
delta = 1;
offset = 0;
}
}
if ( offset == 0xFFFFU )
continue;
@ -1110,11 +1136,21 @@
p += num_segs2;
offset = TT_PEEK_USHORT( p );
/* some fonts handle the last segment incorrectly; */
/* we have to catch it */
if ( mid >= num_segs - 1 &&
start == 0xFFFFU && end == 0xFFFFU && delta == 0x1U )
offset = 0;
/* some fonts have an incorrect last segment; */
/* we have to catch it */
if ( mid >= num_segs - 1 &&
start == 0xFFFFU && end == 0xFFFFU )
{
TT_Face face = (TT_Face)cmap->cmap.charmap.face;
FT_Byte* limit = face->cmap_table + face->cmap_size;
if ( offset && p + offset + 2 > limit )
{
delta = 1;
offset = 0;
}
}
/* search the first segment containing `charcode' */
if ( cmap->flags & TT_CMAP_FLAG_OVERLAPPING )
@ -1580,7 +1616,7 @@
/* */
/* start 0 ULONG first charcode */
/* end 4 ULONG last charcode */
/* startId 8 ULONG start glyph id for the group */
/* startId 8 ULONG start glyph ID for the group */
/* */
#ifdef TT_CONFIG_CMAP_FORMAT_8
@ -1962,7 +1998,7 @@
/* */
/* start 0 ULONG first charcode */
/* end 4 ULONG last charcode */
/* startId 8 ULONG start glyph id for the group */
/* startId 8 ULONG start glyph ID for the group */
/* */
#ifdef TT_CONFIG_CMAP_FORMAT_12