Blob Blame History Raw
From 890ae41d0601d20505df2f955a99d0238bf4f59e Mon Sep 17 00:00:00 2001
From: Pierre Rossi <pierre.rossi@theqtcompany.com>
Date: Wed, 7 Jan 2015 16:16:23 +0100
Subject: [PATCH 012/223] Fix a crash in QPlainTextEdit::documentChanged

The layout for an invalid block is very likely to be null, it
shouldn't be accessed without checking the block's validity first.
We can make the check a bit more conservative and simply check that
the block isn't empty.

Change-Id: Ic1459a6168b1b8ce36e9c6d019dc28653676efbe
Task-number: QTBUG-43562
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
---
 src/widgets/widgets/qplaintextedit.cpp             |  3 +-
 .../widgets/qplaintextedit/tst_qplaintextedit.cpp  | 33 ++++++++++++++++++++++
 2 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp
index 72a556d..e56fd11 100644
--- a/src/widgets/widgets/qplaintextedit.cpp
+++ b/src/widgets/widgets/qplaintextedit.cpp
@@ -288,8 +288,7 @@ void QPlainTextDocumentLayout::documentChanged(int from, int charsRemoved, int c
 
     if (changeStartBlock == changeEndBlock && newBlockCount == d->blockCount) {
         QTextBlock block = changeStartBlock;
-        int blockLineCount = block.layout()->lineCount();
-        if (block.isValid() && blockLineCount) {
+        if (block.isValid() && block.length()) {
             QRectF oldBr = blockBoundingRect(block);
             layoutBlock(block);
             QRectF newBr = blockBoundingRect(block);
diff --git a/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp b/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp
index d8e7fb7..cf495e2 100644
--- a/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp
+++ b/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp
@@ -148,6 +148,7 @@ private slots:
 #endif
     void layoutAfterMultiLineRemove();
     void undoCommandRemovesAndReinsertsBlock();
+    void taskQTBUG_43562_lineCountCrash();
 
 private:
     void createSelection();
@@ -1629,5 +1630,37 @@ void tst_QPlainTextEdit::undoCommandRemovesAndReinsertsBlock()
 
 }
 
+class ContentsChangedFunctor {
+public:
+    ContentsChangedFunctor(QPlainTextEdit *t) : textEdit(t) {}
+    void operator()(int, int, int)
+    {
+        QTextCursor c(textEdit->textCursor());
+        c.beginEditBlock();
+        c.movePosition(QTextCursor::Start);
+        c.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
+        c.setCharFormat(QTextCharFormat());
+        c.endEditBlock();
+    }
+
+private:
+    QPlainTextEdit *textEdit;
+};
+
+void tst_QPlainTextEdit::taskQTBUG_43562_lineCountCrash()
+{
+    connect(ed->document(), &QTextDocument::contentsChange, ContentsChangedFunctor(ed));
+    // Don't crash
+    QTest::keyClicks(ed, "Some text");
+    QTest::keyClick(ed, Qt::Key_Left);
+    QTest::keyClick(ed, Qt::Key_Right);
+    QTest::keyClick(ed, Qt::Key_A);
+    QTest::keyClick(ed, Qt::Key_Left);
+    QTest::keyClick(ed, Qt::Key_Right);
+    QTest::keyClick(ed, Qt::Key_Space);
+    QTest::keyClicks(ed, "nd some more");
+    disconnect(ed->document(), SIGNAL(contentsChange(int, int, int)), 0, 0);
+}
+
 QTEST_MAIN(tst_QPlainTextEdit)
 #include "tst_qplaintextedit.moc"
-- 
1.9.3