Fix QTextEngine regression with large-ish texts
Change 997fd3b88ede8078af286da6ecc197e83a8cbb46 fixed integer overflows with huge texts. This was done by using qsizetype for size calculations instead of int. However, that change introduced a serious regression due to an itermediate imultiplication result being "promoted" to unsigned, and therefore a negative value being converted to a large positive. The solution is to make sure all values in the expression are signed. Fixes: QTBUG-123339 Task-number: QTBUG-119611 Pick-to: 6.7 Change-Id: I3f9189f77b383c6103cf5b35981cdb607b065f6f Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
This commit is contained in:
parent
f944651e3d
commit
7a84c58f55
@ -2658,9 +2658,10 @@ QTextEngine::LayoutData::LayoutData(const QString &str, void **stack_memory, qsi
|
|||||||
{
|
{
|
||||||
allocated = _allocated;
|
allocated = _allocated;
|
||||||
|
|
||||||
qsizetype space_charAttributes = sizeof(QCharAttributes) * string.size() / sizeof(void*) + 1;
|
constexpr qsizetype voidSize = sizeof(void*);
|
||||||
qsizetype space_logClusters = sizeof(unsigned short) * string.size() / sizeof(void*) + 1;
|
qsizetype space_charAttributes = sizeof(QCharAttributes) * string.size() / voidSize + 1;
|
||||||
available_glyphs = (allocated - space_charAttributes - space_logClusters) * sizeof(void*) / QGlyphLayout::SpaceNeeded;
|
qsizetype space_logClusters = sizeof(unsigned short) * string.size() / voidSize + 1;
|
||||||
|
available_glyphs = (allocated - space_charAttributes - space_logClusters) * voidSize / QGlyphLayout::SpaceNeeded;
|
||||||
|
|
||||||
if (available_glyphs < str.size()) {
|
if (available_glyphs < str.size()) {
|
||||||
// need to allocate on the heap
|
// need to allocate on the heap
|
||||||
|
@ -159,10 +159,8 @@ Q_DECLARE_TYPEINFO(QGlyphAttributes, Q_PRIMITIVE_TYPE);
|
|||||||
|
|
||||||
struct QGlyphLayout
|
struct QGlyphLayout
|
||||||
{
|
{
|
||||||
enum {
|
static constexpr qsizetype SpaceNeeded = sizeof(glyph_t) + sizeof(QFixed) + sizeof(QFixedPoint)
|
||||||
SpaceNeeded = sizeof(glyph_t) + sizeof(QFixed) + sizeof(QFixedPoint)
|
+ sizeof(QGlyphAttributes) + sizeof(QGlyphJustification);
|
||||||
+ sizeof(QGlyphAttributes) + sizeof(QGlyphJustification)
|
|
||||||
};
|
|
||||||
|
|
||||||
// init to 0 not needed, done when shaping
|
// init to 0 not needed, done when shaping
|
||||||
QFixedPoint *offsets; // 8 bytes per element
|
QFixedPoint *offsets; // 8 bytes per element
|
||||||
|
@ -34,6 +34,8 @@ private slots:
|
|||||||
void zeroWidthMetrics();
|
void zeroWidthMetrics();
|
||||||
void verticalMetrics_data();
|
void verticalMetrics_data();
|
||||||
void verticalMetrics();
|
void verticalMetrics();
|
||||||
|
void largeText_data();
|
||||||
|
void largeText(); // QTBUG-123339
|
||||||
};
|
};
|
||||||
|
|
||||||
void tst_QFontMetrics::same()
|
void tst_QFontMetrics::same()
|
||||||
@ -388,5 +390,25 @@ void tst_QFontMetrics::verticalMetrics()
|
|||||||
QVERIFY(fm.ascent() != 0 || fm.descent() != 0);
|
QVERIFY(fm.ascent() != 0 || fm.descent() != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QFontMetrics::largeText_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<qsizetype>("size");
|
||||||
|
for (int i = 1; i < 20; ++i) {
|
||||||
|
qsizetype size = qsizetype(1) << i;
|
||||||
|
QByteArray rowText = QByteArray::number(size);
|
||||||
|
QTest::newRow(rowText.constData()) << size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QFontMetrics::largeText()
|
||||||
|
{
|
||||||
|
QFont font;
|
||||||
|
QFontMetrics fm(font);
|
||||||
|
QFETCH(qsizetype, size);
|
||||||
|
QString string(size, QLatin1Char('A'));
|
||||||
|
QRect boundingRect = fm.boundingRect(string);
|
||||||
|
QVERIFY(boundingRect.isValid());
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_QFontMetrics)
|
QTEST_MAIN(tst_QFontMetrics)
|
||||||
#include "tst_qfontmetrics.moc"
|
#include "tst_qfontmetrics.moc"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user