Fix crash when detaching dangling QTextCursor

When a QTextCursor survives its QTextDocument, the internal
QTextDocumentPrivate pointer is set to null. There are checks for
this in all the QTextCursor functions to skip out early if such
a QTextCursor is used.

However, when executing the "if (d->priv)" condition in setters,
this will access the non-const operator->() of QSharedDataPointer
and detach the QTextCursorPrivate, and in the copy constructor of
this class, there was an unprotected call into priv->addCursor().

In theory, we could cast all the checks for d->priv to avoid
detaching, but in practice this doesn't matter, since the setters
will typically detach anyway later on.

[ChangeLog][QtGui][Text] Fixed a crash that can happen when calling
a setter on a QTextCursor after its QTextDocument has been deleted.

Task-number: QTBUG-70293
Change-Id: I8f6dc5bb344d1d824f673c0c220b68b7fee237a8
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
bb10
Eskil Abrahamsen Blomfeldt 2018-09-20 12:07:37 +02:00
parent 9601ad4e27
commit 720e243d88
2 changed files with 12 additions and 1 deletions

View File

@ -80,7 +80,8 @@ QTextCursorPrivate::QTextCursorPrivate(const QTextCursorPrivate &rhs)
visualNavigation = rhs.visualNavigation;
keepPositionOnInsert = rhs.keepPositionOnInsert;
changed = rhs.changed;
priv->addCursor(this);
if (priv != nullptr)
priv->addCursor(this);
}
QTextCursorPrivate::~QTextCursorPrivate()

View File

@ -137,6 +137,7 @@ private slots:
void cursorPositionWithBlockUndoAndRedo3();
void joinNonEmptyRemovedBlockUserState();
void crashOnDetachingDanglingCursor();
private:
int blockCount();
@ -1974,5 +1975,14 @@ void tst_QTextCursor::joinNonEmptyRemovedBlockUserState()
QCOMPARE(cursor.block().userState(), 10);
}
void tst_QTextCursor::crashOnDetachingDanglingCursor()
{
QTextDocument *document = new QTextDocument;
QTextCursor cursor(document);
QTextCursor cursor2 = cursor;
delete document;
cursor2.setPosition(0); // Don't crash here
}
QTEST_MAIN(tst_QTextCursor)
#include "tst_qtextcursor.moc"