From 659bb338fe113beec5ddccde9cc3905b499f75a3 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Fri, 21 Apr 2023 13:24:47 +0200 Subject: [PATCH] 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 (cherry picked from commit 1dc88a1b5f826219a58cefc03b4118917be2da96) Reviewed-by: Qt Cherry-pick Bot --- src/gui/text/qtextdocumentlayout.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp index fe049766ab8..254960522db 100644 --- a/src/gui/text/qtextdocumentlayout.cpp +++ b/src/gui/text/qtextdocumentlayout.cpp @@ -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);