Avoid infinite loop when loading huge files

QTextDocumentLayout could get into an infinite loop when the
contents exceeded QFIXED_MAX.

Specifically, QFIXED_MAX is used as meaning "one infinite page"
which means that newPage() will just return when it sees this
page height. If the page actually grew larger than this, though,
we would treat it as a page break and enter a loop where we try
to call newPage() to create new pages and never return.

The layout engine cannot support documents this large, so we detect
the case and then just finish the layout loop early when it is
encountered.

Fixes: QTBUG-112968
Change-Id: I485303d714d112119a971c43e0086bf6d3d23e9f
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
(cherry picked from commit 1dc88a1b5f826219a58cefc03b4118917be2da96)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Eskil Abrahamsen Blomfeldt 2023-04-21 13:24:47 +02:00 committed by Qt Cherry-pick Bot
parent 7a42679a98
commit 659bb338fe

View File

@ -3111,7 +3111,7 @@ void QTextDocumentLayoutPrivate::layoutFlow(QTextFrame::Iterator it, QTextLayout
QTextBlockFormat previousBlockFormat = previousIt.currentBlock().blockFormat();
QFixed maximumBlockWidth = 0;
while (!it.atEnd()) {
while (!it.atEnd() && layoutStruct->absoluteY() < QFIXED_MAX) {
QTextFrame *c = it.currentFrame();
int docPos;
@ -3361,7 +3361,7 @@ void QTextDocumentLayoutPrivate::layoutFlow(QTextFrame::Iterator it, QTextLayout
if (!fd->floats.isEmpty())
contentHasAlignment = true;
if (it.atEnd()) {
if (it.atEnd() || layoutStruct->absoluteY() >= QFIXED_MAX) {
//qDebug("layout done!");
currentLazyLayoutPosition = -1;
QCheckPoint cp;
@ -3547,6 +3547,11 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
while (layoutStruct->pageHeight > 0 && layoutStruct->absoluteY() + lineBreakHeight > layoutStruct->pageBottom &&
layoutStruct->contentHeight() >= lineBreakHeight) {
if (layoutStruct->pageHeight == QFIXED_MAX) {
layoutStruct->y = QFIXED_MAX - layoutStruct->frameY;
break;
}
layoutStruct->newPage();
floatMargins(layoutStruct->y, layoutStruct, &left, &right);