ref: 801e7bae3a31047d280c6c853c8046ea4f399eaf
parent: 34ca21edc6ed4817928f2f5eee408ddd1129ed62
author: Werner Lemberg <[email protected]>
date: Wed Mar 11 02:47:49 EDT 2009
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.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
2009-03-11 Werner Lemberg <[email protected]>
+ 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 <[email protected]>
+
* src/base/Jamfile: Fix handling of ftadvanc.c.
Reported by Oran Agra <[email protected]>.
--- a/src/sfnt/ttcmap.c
+++ b/src/sfnt/ttcmap.c
@@ -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,14 +697,23 @@
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 )
{
cmap->cur_values = offset ? p + offset : NULL;
@@ -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,12 +1041,22 @@
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,12 +1136,22 @@
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