From 827e5c4c689d4ecb4f8c1ab48c9a7ab712fe2ca7 Mon Sep 17 00:00:00 2001 From: John Tapsell Date: Mon, 12 Mar 2012 22:07:47 +0000 Subject: Harfbuzz-thai - fix buffer overflow when setting item attributes Change-Id: I19eeb4ec25a7c6cb3f584e6290169f9f327b8713 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/3rdparty/harfbuzz/src/harfbuzz-thai.c | 9 +++++-- .../qtextscriptengine/tst_qtextscriptengine.cpp | 29 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-thai.c b/src/3rdparty/harfbuzz/src/harfbuzz-thai.c index bf6c35b..3c0ffe8 100644 --- a/src/3rdparty/harfbuzz/src/harfbuzz-thai.c +++ b/src/3rdparty/harfbuzz/src/harfbuzz-thai.c @@ -263,8 +263,13 @@ static HB_Bool HB_ThaiConvertStringToGlyphIndices (HB_ShaperItem *item) // The only glyphs that should be passed to this function that cannot be mapped to // tis620 are the ones of type Inherited class. Pass these glyphs untouched. glyphString[slen++] = string[i]; - if (string[i] == 0x200D || string[i] == 0x200C) - item->attributes[slen-1].dontPrint = true; // Hide ZWJ and ZWNJ characters + if (string[i] == 0x200D || string[i] == 0x200C) { + // Check that we do not run out of bounds when setting item->attributes. If we do + // run out of bounds then this function will return false, the necessary amount of + // memory is reallocated, and this function will then be called again. + if (slen <= item->num_glyphs) + item->attributes[slen-1].dontPrint = true; // Hide ZWJ and ZWNJ characters + } } else { glyphString[slen++] = (HB_UChar16) thai_get_glyph_index (font_type, rglyphs[lgi]); } diff --git a/tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp b/tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp index 113f110..a45107a 100644 --- a/tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp +++ b/tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp @@ -116,6 +116,7 @@ private slots: void thaiWithZWJ(); void thaiLineSplitting(); void thaiSaraAM(); + void thaiMultipleVowels(); }; tst_QTextScriptEngine::tst_QTextScriptEngine() @@ -1355,5 +1356,33 @@ void tst_QTextScriptEngine::thaiSaraAM() QCOMPARE(e->layoutData->logClustersPtr[i], clusterNumber[i]); } +void tst_QTextScriptEngine::thaiMultipleVowels() +{ + QString s(QString::fromUtf8("ส")); + for (int i = 0; i < 100; i++) + s += QChar(0x0E47); // Add lots of "VOWEL SIGN MAI TAI KHU N/S-T" stacked on top of the character + s += QChar(0x200D); // Now add a zero width joiner (which adds a circle which is hidden) + for (int i = 0; i < 100; i++) + s += QChar(0x0E47); //Add lots of "VOWEL SIGN MAI TAI KHU N/S-T" stacked on top of the ZWJ + + for (int i = 0; i < 10; i++) + s += s; //Repeat the string to make it more likely to crash if we have a buffer overflow + QTextLayout layout(s); + layout.beginLayout(); + layout.createLine(); + layout.endLayout(); + + QTextEngine *e = layout.engine(); + e->width(0, s.length()); //force itemize and shape + + int k = 0; + for (int i = 0; i < e->layoutData->items.size(); i++) + for (int j = 0; j < e->layoutData->items[i].num_glyphs; j++) { + bool isZWJ = k%401 == 200; + QCOMPARE((bool)e->layoutData->glyphLayout.attributes[k++].dontPrint, isZWJ); + } +} + + QTEST_MAIN(tst_QTextScriptEngine) #include "tst_qtextscriptengine.moc" -- cgit v0.12