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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
diff --git a/ChangeLog b/ChangeLog
index 1a1dedc..32660ab 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
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.
Reported by Oran Agra <oran@monfort.co.il>.
diff --git a/src/sfnt/ttcmap.c b/src/sfnt/ttcmap.c
index 67b6684..6830391 100644
--- 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,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