From 890ae41d0601d20505df2f955a99d0238bf4f59e Mon Sep 17 00:00:00 2001 From: Pierre Rossi 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 --- 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