1 From 0a2f2382541424726168804be2c90b91381608c6 Mon Sep 17 00:00:00 2001
2 From: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@theqtcompany.com>
3 Date: Fri, 10 Jul 2015 13:22:32 +0200
4 Subject: [PATCH] Better handling of invalid font tables
6 Specifically when reading files with broken cmap tables, we could
7 get some undeterministic results. We handle this more gracefully
8 by verifying that the offsets are sane and bailing out early if not.
9 This replaces the current pattern throughout the font engine for
12 This is a back-port of 4a1e5dbade4bab55f39bd368480dcca9a11e4b38
15 Change-Id: If4172b9ef0808801c8e27ffaad962535afe572ed
16 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
17 Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
19 src/gui/text/qfontengine.cpp | 212 +++++++++++++++++++++++++++++----------
20 src/gui/text/qfontengine_mac.mm | 11 +-
21 src/gui/text/qfontengine_mac_p.h | 1 +
22 src/gui/text/qfontengine_p.h | 2 +-
23 src/gui/text/qfontengine_qpa.cpp | 12 +--
24 src/gui/text/qfontengine_qpf.cpp | 12 +--
25 src/gui/text/qfontengine_s60.cpp | 9 +-
26 src/gui/text/qfontengine_s60_p.h | 1 +
27 src/gui/text/qfontengine_win.cpp | 22 ++--
28 src/gui/text/qfontengine_win_p.h | 1 +
29 10 files changed, 198 insertions(+), 85 deletions(-)
31 diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
32 index 67b8798..3f7d831 100644
33 --- a/src/gui/text/qfontengine.cpp
34 +++ b/src/gui/text/qfontengine.cpp
35 @@ -69,6 +69,16 @@ static inline bool qtransform_equals_no_translate(const QTransform &a, const QTr
40 +static inline bool qSafeFromBigEndian(const uchar *source, const uchar *end, T *output)
42 + if (source + sizeof(T) > end)
45 + *output = qFromBigEndian<T>(source);
49 // Harfbuzz helper functions
51 static HB_Bool hb_stringToGlyphs(HB_Font font, const HB_UChar16 *string, hb_uint32 length, HB_Glyph *glyphs, hb_uint32 *numGlyphs, HB_Bool rightToLeft)
52 @@ -808,26 +818,38 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor)
55 const uchar *table = reinterpret_cast<const uchar *>(tab.constData());
56 + const uchar *end = table + tab.size();
59 + if (!qSafeFromBigEndian(table, end, &version))
62 - unsigned short version = qFromBigEndian<quint16>(table);
64 // qDebug("wrong version");
68 - unsigned short numTables = qFromBigEndian<quint16>(table + 2);
70 + if (!qSafeFromBigEndian(table + 2, end, &numTables))
75 for(int i = 0; i < numTables; ++i) {
76 - if (offset + 6 > tab.size()) {
77 -// qDebug("offset out of bounds");
80 const uchar *header = table + offset;
82 - ushort version = qFromBigEndian<quint16>(header);
83 - ushort length = qFromBigEndian<quint16>(header+2);
84 - ushort coverage = qFromBigEndian<quint16>(header+4);
86 + if (!qSafeFromBigEndian(header, end, &version))
90 + if (!qSafeFromBigEndian(header + 2, end, &length))
94 + if (!qSafeFromBigEndian(header + 4, end, &coverage))
97 // qDebug("subtable: version=%d, coverage=%x",version, coverage);
98 if(version == 0 && coverage == 0x0001) {
99 if (offset + length > tab.size()) {
100 @@ -836,7 +858,10 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor)
102 const uchar *data = table + offset + 6;
104 - ushort nPairs = qFromBigEndian<quint16>(data);
106 + if (!qSafeFromBigEndian(data, end, &nPairs))
109 if(nPairs * 6 + 8 > length - 6) {
110 // qDebug("corrupt table!");
112 @@ -846,8 +871,21 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor)
114 for(int i = 0; i < nPairs; ++i) {
115 QFontEngine::KernPair p;
116 - p.left_right = (((uint)qFromBigEndian<quint16>(data+off)) << 16) + qFromBigEndian<quint16>(data+off+2);
117 - p.adjust = QFixed(((int)(short)qFromBigEndian<quint16>(data+off+4))) / scalingFactor;
120 + if (!qSafeFromBigEndian(data + off, end, &tmp))
123 + p.left_right = uint(tmp) << 16;
124 + if (!qSafeFromBigEndian(data + off + 2, end, &tmp))
127 + p.left_right |= tmp;
129 + if (!qSafeFromBigEndian(data + off + 4, end, &tmp))
132 + p.adjust = QFixed(int(short(tmp))) / scalingFactor;
133 kerning_pairs.append(p);
136 @@ -872,26 +910,31 @@ int QFontEngine::glyphCount() const
137 QByteArray maxpTable = getSfntTable(MAKE_TAG('m', 'a', 'x', 'p'));
138 if (maxpTable.size() < 6)
140 - return qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(maxpTable.constData() + 4));
142 + const uchar *source = reinterpret_cast<const uchar *>(maxpTable.constData() + 4);
143 + const uchar *end = source + maxpTable.size();
146 + qSafeFromBigEndian(source, end, &count);
150 const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize)
152 const uchar *header = table;
156 const uchar *endPtr = table + tableSize;
159 - if (qFromBigEndian<quint16>(header) != 0)
161 + if (!qSafeFromBigEndian(header, endPtr, &version) || version != 0)
164 - unsigned short numTables = qFromBigEndian<quint16>(header + 2);
165 - const uchar *maps = table + 4;
166 - if (maps + 8 * numTables > endPtr)
168 + if (!qSafeFromBigEndian(header + 2, endPtr, &numTables))
171 + const uchar *maps = table + 4;
176 @@ -906,8 +949,14 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy
179 for (int n = 0; n < numTables; ++n) {
180 - const quint16 platformId = qFromBigEndian<quint16>(maps + 8 * n);
181 - const quint16 platformSpecificId = qFromBigEndian<quint16>(maps + 8 * n + 2);
182 + quint16 platformId;
183 + if (!qSafeFromBigEndian(maps + 8 * n, endPtr, &platformId))
186 + quint16 platformSpecificId;
187 + if (!qSafeFromBigEndian(maps + 8 * n + 2, endPtr, &platformSpecificId))
190 switch (platformId) {
192 if (score < Unicode &&
193 @@ -961,20 +1010,30 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy
195 *isSymbolFont = (symbolTable > -1);
197 - unsigned int unicode_table = qFromBigEndian<quint32>(maps + 8*tableToUse + 4);
198 + quint32 unicode_table;
199 + if (!qSafeFromBigEndian(maps + 8 * tableToUse + 4, endPtr, &unicode_table))
202 - if (!unicode_table || unicode_table + 8 > tableSize)
203 + if (!unicode_table)
206 // get the header of the unicode table
207 header = table + unicode_table;
209 - unsigned short format = qFromBigEndian<quint16>(header);
210 - unsigned int length;
212 - length = qFromBigEndian<quint16>(header + 2);
214 - length = qFromBigEndian<quint32>(header + 4);
216 + if (!qSafeFromBigEndian(header, endPtr, &format))
222 + if (!qSafeFromBigEndian(header + 2, endPtr, &tmp))
226 + if (!qSafeFromBigEndian(header + 4, endPtr, &length))
230 if (table + unicode_table + length > endPtr)
232 @@ -989,7 +1048,7 @@ resolveTable:
233 // Check that none of the latin1 range are in the unicode table
234 bool unicodeTableHasLatin1 = false;
235 for (int uc=0x00; uc<0x100; ++uc) {
236 - if (getTrueTypeGlyphIndex(selectedTable, uc) != 0) {
237 + if (getTrueTypeGlyphIndex(selectedTable, length, uc) != 0) {
238 unicodeTableHasLatin1 = true;
241 @@ -999,7 +1058,7 @@ resolveTable:
242 bool unicodeTableHasSymbols = false;
243 if (!unicodeTableHasLatin1) {
244 for (int uc=0xf000; uc<0xf100; ++uc) {
245 - if (getTrueTypeGlyphIndex(selectedTable, uc) != 0) {
246 + if (getTrueTypeGlyphIndex(selectedTable, length, uc) != 0) {
247 unicodeTableHasSymbols = true;
250 @@ -1017,12 +1076,17 @@ resolveTable:
251 return table + unicode_table;
254 -quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
255 +quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint unicode)
257 - unsigned short format = qFromBigEndian<quint16>(cmap);
258 + const uchar *end = cmap + cmapSize;
260 + if (!qSafeFromBigEndian(cmap, end, &format))
265 - return (int) *(cmap+6+unicode);
266 + const uchar *ptr = cmap + 6 + unicode;
267 + if (unicode < 256 && ptr < end)
268 + return quint32(*ptr);
269 } else if (format == 4) {
270 /* some fonts come with invalid cmap tables, where the last segment
271 specified end = start = rangeoffset = 0xffff, delta = 0x0001
272 @@ -1031,25 +1095,49 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
274 if(unicode >= 0xffff)
276 - quint16 segCountX2 = qFromBigEndian<quint16>(cmap + 6);
278 + quint16 segCountX2;
279 + if (!qSafeFromBigEndian(cmap + 6, end, &segCountX2))
282 const unsigned char *ends = cmap + 14;
285 - for (; i < segCountX2/2 && qFromBigEndian<quint16>(ends + 2*i) < unicode; i++) {}
286 + for (; i < segCountX2/2; ++i) {
288 + if (!qSafeFromBigEndian(ends + 2 * i, end, &codePoint))
290 + if (codePoint >= unicode)
294 const unsigned char *idx = ends + segCountX2 + 2 + 2*i;
295 - quint16 startIndex = qFromBigEndian<quint16>(idx);
297 + quint16 startIndex;
298 + if (!qSafeFromBigEndian(idx, end, &startIndex))
300 if (startIndex > unicode)
304 - qint16 idDelta = (qint16)qFromBigEndian<quint16>(idx);
307 + if (!qSafeFromBigEndian(idx, end, &tmp))
309 + qint16 idDelta = qint16(tmp);
312 - quint16 idRangeoffset_t = (quint16)qFromBigEndian<quint16>(idx);
314 + quint16 idRangeoffset_t;
315 + if (!qSafeFromBigEndian(idx, end, &idRangeoffset_t))
319 if (idRangeoffset_t) {
320 - quint16 id = qFromBigEndian<quint16>(idRangeoffset_t + 2*(unicode - startIndex) + idx);
322 + if (!qSafeFromBigEndian(idRangeoffset_t + 2 * (unicode - startIndex) + idx, end, &id))
326 glyphIndex = (idDelta + id) % 0x10000;
328 @@ -1059,13 +1147,19 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
331 } else if (format == 6) {
332 - quint16 tableSize = qFromBigEndian<quint16>(cmap + 2);
334 + if (!qSafeFromBigEndian(cmap + 2, end, &tableSize))
337 - quint16 firstCode6 = qFromBigEndian<quint16>(cmap + 6);
338 + quint16 firstCode6;
339 + if (!qSafeFromBigEndian(cmap + 6, end, &firstCode6))
341 if (unicode < firstCode6)
344 - quint16 entryCount6 = qFromBigEndian<quint16>(cmap + 8);
345 + quint16 entryCount6;
346 + if (!qSafeFromBigEndian(cmap + 8, end, &entryCount6))
348 if (entryCount6 * 2 + 10 > tableSize)
351 @@ -1074,9 +1168,14 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
354 quint16 entryIndex6 = unicode - firstCode6;
355 - return qFromBigEndian<quint16>(cmap + 10 + (entryIndex6 * 2));
358 + qSafeFromBigEndian(cmap + 10 + (entryIndex6 * 2), end, &index);
360 } else if (format == 12) {
361 - quint32 nGroups = qFromBigEndian<quint32>(cmap + 12);
363 + if (!qSafeFromBigEndian(cmap + 12, end, &nGroups))
366 cmap += 16; // move to start of groups
368 @@ -1084,13 +1183,24 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
369 while (left <= right) {
370 int middle = left + ( ( right - left ) >> 1 );
372 - quint32 startCharCode = qFromBigEndian<quint32>(cmap + 12*middle);
373 + quint32 startCharCode;
374 + if (!qSafeFromBigEndian(cmap + 12 * middle, end, &startCharCode))
377 if(unicode < startCharCode)
380 - quint32 endCharCode = qFromBigEndian<quint32>(cmap + 12*middle + 4);
381 - if(unicode <= endCharCode)
382 - return qFromBigEndian<quint32>(cmap + 12*middle + 8) + unicode - startCharCode;
383 + quint32 endCharCode;
384 + if (!qSafeFromBigEndian(cmap + 12 * middle + 4, end, &endCharCode))
387 + if (unicode <= endCharCode) {
389 + if (!qSafeFromBigEndian(cmap + 12 * middle + 8, end, &index))
392 + return index + unicode - startCharCode;
397 diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm
398 index ba01f4c..460aa5f 100644
399 --- a/src/gui/text/qfontengine_mac.mm
400 +++ b/src/gui/text/qfontengine_mac.mm
401 @@ -625,7 +625,7 @@ bool QFontEngineMacMulti::canRender(const QChar *string, int len)
404 QFontEngineMac::QFontEngineMac(ATSUStyle baseStyle, ATSUFontID fontID, const QFontDef &def, QFontEngineMacMulti *multiEngine)
405 - : fontID(fontID), multiEngine(multiEngine), cmap(0), symbolCMap(false)
406 + : fontID(fontID), multiEngine(multiEngine), cmap(0), symbolCMap(false), cmapSize(0)
409 ATSUCreateAndCopyStyle(baseStyle, &style);
410 @@ -747,22 +747,21 @@ bool QFontEngineMac::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph
413 cmapTable = getSfntTable(MAKE_TAG('c', 'm', 'a', 'p'));
415 - cmap = getCMap(reinterpret_cast<const uchar *>(cmapTable.constData()), cmapTable.size(), &symbolCMap, &size);
416 + cmap = getCMap(reinterpret_cast<const uchar *>(cmapTable.constData()), cmapTable.size(), &symbolCMap, &cmapSize);
421 for (int i = 0; i < len; ++i) {
422 unsigned int uc = getChar(str, i, len);
423 - glyphs->glyphs[i] = getTrueTypeGlyphIndex(cmap, uc);
424 + glyphs->glyphs[i] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
425 if(!glyphs->glyphs[i] && uc < 0x100)
426 - glyphs->glyphs[i] = getTrueTypeGlyphIndex(cmap, uc + 0xf000);
427 + glyphs->glyphs[i] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000);
430 for (int i = 0; i < len; ++i) {
431 unsigned int uc = getChar(str, i, len);
432 - glyphs->glyphs[i] = getTrueTypeGlyphIndex(cmap, uc);
433 + glyphs->glyphs[i] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
437 diff --git a/src/gui/text/qfontengine_mac_p.h b/src/gui/text/qfontengine_mac_p.h
438 index 7d70c24..844d421 100644
439 --- a/src/gui/text/qfontengine_mac_p.h
440 +++ b/src/gui/text/qfontengine_mac_p.h
441 @@ -108,6 +108,7 @@ private:
442 qreal m_maxCharWidth;
444 QFixed m_averageCharWidth;
445 + mutable int cmapSize;
448 class QFontEngineMacMulti : public QFontEngineMulti
449 diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
450 index f29ac47..9c3435f 100644
451 --- a/src/gui/text/qfontengine_p.h
452 +++ b/src/gui/text/qfontengine_p.h
453 @@ -247,7 +247,7 @@ public:
454 QFontEngineGlyphCache *glyphCache(void *key, QFontEngineGlyphCache::Type type, const QTransform &transform) const;
456 static const uchar *getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize);
457 - static quint32 getTrueTypeGlyphIndex(const uchar *cmap, uint unicode);
458 + static quint32 getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint unicode);
460 static QByteArray convertToPostscriptFontFamilyName(const QByteArray &fontFamily);
462 diff --git a/src/gui/text/qfontengine_qpa.cpp b/src/gui/text/qfontengine_qpa.cpp
463 index 04f7b76..011d233 100644
464 --- a/src/gui/text/qfontengine_qpa.cpp
465 +++ b/src/gui/text/qfontengine_qpa.cpp
466 @@ -358,9 +358,9 @@ bool QFontEngineQPA::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph
467 unsigned int uc = getChar(str, i, len);
469 uc = QChar::mirroredChar(uc);
470 - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc);
471 + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
472 if(!glyphs->glyphs[glyph_pos] && uc < 0x100)
473 - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000);
474 + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000);
478 @@ -368,7 +368,7 @@ bool QFontEngineQPA::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph
479 unsigned int uc = getChar(str, i, len);
481 uc = QChar::mirroredChar(uc);
482 - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc);
483 + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
484 #if 0 && defined(DEBUG_FONTENGINE)
486 if (!findGlyph(glyphs[glyph_pos].glyph) && !seenGlyphs.contains(c))
487 @@ -511,16 +511,16 @@ bool QFontEngineQPA::canRender(const QChar *string, int len)
489 for (int i = 0; i < len; ++i) {
490 unsigned int uc = getChar(string, i, len);
491 - glyph_t g = getTrueTypeGlyphIndex(cmap, uc);
492 + glyph_t g = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
494 - g = getTrueTypeGlyphIndex(cmap, uc + 0xf000);
495 + g = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000);
500 for (int i = 0; i < len; ++i) {
501 unsigned int uc = getChar(string, i, len);
502 - if (!getTrueTypeGlyphIndex(cmap, uc))
503 + if (!getTrueTypeGlyphIndex(cmap, cmapSize, uc))
507 diff --git a/src/gui/text/qfontengine_qpf.cpp b/src/gui/text/qfontengine_qpf.cpp
508 index 8d5e71b..9087cff 100644
509 --- a/src/gui/text/qfontengine_qpf.cpp
510 +++ b/src/gui/text/qfontengine_qpf.cpp
511 @@ -577,9 +577,9 @@ bool QFontEngineQPF::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph
513 for (int i = 0; i < len; ++i) {
514 unsigned int uc = getChar(str, i, len);
515 - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc);
516 + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
517 if(!glyphs->glyphs[glyph_pos] && uc < 0x100)
518 - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000);
519 + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000);
523 @@ -587,7 +587,7 @@ bool QFontEngineQPF::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph
524 unsigned int uc = getChar(str, i, len);
526 uc = QChar::mirroredChar(uc);
527 - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc);
528 + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
529 #if 0 && defined(DEBUG_FONTENGINE)
531 if (!findGlyph(glyphs[glyph_pos].glyph) && !seenGlyphs.contains(c))
532 @@ -786,16 +786,16 @@ bool QFontEngineQPF::canRender(const QChar *string, int len)
534 for (int i = 0; i < len; ++i) {
535 unsigned int uc = getChar(string, i, len);
536 - glyph_t g = getTrueTypeGlyphIndex(cmap, uc);
537 + glyph_t g = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
539 - g = getTrueTypeGlyphIndex(cmap, uc + 0xf000);
540 + g = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000);
545 for (int i = 0; i < len; ++i) {
546 unsigned int uc = getChar(string, i, len);
547 - if (!getTrueTypeGlyphIndex(cmap, uc))
548 + if (!getTrueTypeGlyphIndex(cmap, cmapSize, uc))
552 diff --git a/src/gui/text/qfontengine_s60.cpp b/src/gui/text/qfontengine_s60.cpp
553 index 1da501a..b2bb561 100644
554 --- a/src/gui/text/qfontengine_s60.cpp
555 +++ b/src/gui/text/qfontengine_s60.cpp
556 @@ -77,6 +77,7 @@ QSymbianTypeFaceExtras::QSymbianTypeFaceExtras(CFont* cFont, COpenFont *openFont
558 , m_symbolCMap(false)
559 , m_openFont(openFont)
562 if (!symbianFontTableApiAvailable()) {
563 TAny *trueTypeExtension = NULL;
564 @@ -161,10 +162,9 @@ const uchar *QSymbianTypeFaceExtras::cmap() const
566 if (m_cmapTable.isNull()) {
567 const QByteArray cmapTable = getSfntTable(MAKE_TAG('c', 'm', 'a', 'p'));
569 const uchar *cmap = QFontEngine::getCMap(reinterpret_cast<const uchar *>
570 - (cmapTable.constData()), cmapTable.size(), &m_symbolCMap, &size);
571 - m_cmapTable = QByteArray(reinterpret_cast<const char *>(cmap), size);
572 + (cmapTable.constData()), cmapTable.size(), &m_symbolCMap, &m_cmapSize);
573 + m_cmapTable = QByteArray(reinterpret_cast<const char *>(cmap), m_cmapSize);
575 return reinterpret_cast<const uchar *>(m_cmapTable.constData());
577 @@ -324,6 +324,7 @@ bool QFontEngineS60::stringToCMap(const QChar *characters, int len, QGlyphLayout
578 for (int i = 0; i < len; ++i) {
579 const unsigned int uc = getChar(characters, i, len);
580 *g++ = QFontEngine::getTrueTypeGlyphIndex(cmap,
582 (isRtl && !m_extras->isSymbolCMap()) ? QChar::mirroredChar(uc) : uc);
585 @@ -463,7 +464,7 @@ bool QFontEngineS60::canRender(const QChar *string, int len)
586 const unsigned char *cmap = m_extras->cmap();
587 for (int i = 0; i < len; ++i) {
588 const unsigned int uc = getChar(string, i, len);
589 - if (QFontEngine::getTrueTypeGlyphIndex(cmap, uc) == 0)
590 + if (QFontEngine::getTrueTypeGlyphIndex(cmap, m_cmapSize, uc) == 0)
594 diff --git a/src/gui/text/qfontengine_s60_p.h b/src/gui/text/qfontengine_s60_p.h
595 index 17e2207..9e38570 100644
596 --- a/src/gui/text/qfontengine_s60_p.h
597 +++ b/src/gui/text/qfontengine_s60_p.h
598 @@ -93,6 +93,7 @@ private:
599 // the Font Table API
600 COpenFont *m_openFont;
601 mutable MOpenFontTrueTypeExtension *m_trueTypeExtension;
602 + mutable int m_cmapSize;
605 class QFontEngineS60 : public QFontEngine
606 diff --git a/src/gui/text/qfontengine_win.cpp b/src/gui/text/qfontengine_win.cpp
607 index bd9a437..6ad5eb4 100644
608 --- a/src/gui/text/qfontengine_win.cpp
609 +++ b/src/gui/text/qfontengine_win.cpp
610 @@ -215,9 +215,8 @@ void QFontEngineWin::getCMap()
613 cmapTable = getSfntTable(qbswap<quint32>(MAKE_TAG('c', 'm', 'a', 'p')));
615 cmap = QFontEngine::getCMap(reinterpret_cast<const uchar *>(cmapTable.constData()),
616 - cmapTable.size(), &symb, &size);
617 + cmapTable.size(), &symb, &cmapSize);
621 @@ -263,14 +262,14 @@ int QFontEngineWin::getGlyphIndexes(const QChar *str, int numChars, QGlyphLayout
623 for (; i < numChars; ++i, ++glyph_pos) {
624 unsigned int uc = getChar(str, i, numChars);
625 - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc);
626 + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
627 if (!glyphs->glyphs[glyph_pos] && uc < 0x100)
628 - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000);
629 + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000);
632 for (; i < numChars; ++i, ++glyph_pos) {
633 unsigned int uc = getChar(str, i, numChars);
634 - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, QChar::mirroredChar(uc));
635 + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, QChar::mirroredChar(uc));
639 @@ -296,14 +295,14 @@ int QFontEngineWin::getGlyphIndexes(const QChar *str, int numChars, QGlyphLayout
641 for (; i < numChars; ++i, ++glyph_pos) {
642 unsigned int uc = getChar(str, i, numChars);
643 - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc);
644 + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
645 if(!glyphs->glyphs[glyph_pos] && uc < 0x100)
646 - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000);
647 + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000);
650 for (; i < numChars; ++i, ++glyph_pos) {
651 unsigned int uc = getChar(str, i, numChars);
652 - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc);
653 + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
657 @@ -335,6 +334,7 @@ QFontEngineWin::QFontEngineWin(const QString &name, HFONT _hfont, bool stockFont
664 HDC hdc = shared_dc();
665 @@ -811,9 +811,9 @@ bool QFontEngineWin::canRender(const QChar *string, int len)
667 for (int i = 0; i < len; ++i) {
668 unsigned int uc = getChar(string, i, len);
669 - if (getTrueTypeGlyphIndex(cmap, uc) == 0) {
670 + if (getTrueTypeGlyphIndex(cmap, cmapSize, uc) == 0) {
672 - if (getTrueTypeGlyphIndex(cmap, uc + 0xf000) == 0)
673 + if (getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000) == 0)
677 @@ -823,7 +823,7 @@ bool QFontEngineWin::canRender(const QChar *string, int len)
679 for (int i = 0; i < len; ++i) {
680 unsigned int uc = getChar(string, i, len);
681 - if (getTrueTypeGlyphIndex(cmap, uc) == 0)
682 + if (getTrueTypeGlyphIndex(cmap, cmapSize, uc) == 0)
686 diff --git a/src/gui/text/qfontengine_win_p.h b/src/gui/text/qfontengine_win_p.h
687 index 0c8df72..27f0355 100644
688 --- a/src/gui/text/qfontengine_win_p.h
689 +++ b/src/gui/text/qfontengine_win_p.h
690 @@ -144,6 +144,7 @@ public:
691 mutable uint widthCacheSize;
692 mutable QFixed *designAdvances;
693 mutable int designAdvancesSize;
697 bool hasCFFTable() const;