Fix crash in QTextDocument::clearUndoRedoStacks()

When calling QTextDocument::clearUndoRedoStacks() with UndoStack,
there were two bugs: The first was that we were retrieving
the item at "undoState" and deleting this. This is actually the
upper limit of the for loop. If the stack does not contain any
redos, then it would be == undoStack.size() and we would assert.

If there were redos, then we would delete the item at undoState
multiple times (actually undoState times).

In addition, when the loop exited, we first removed the dangling
pointers using remove() and then there was a weird resize() to
the new size minus the old undoState.

This would either assert because we tried to resize to a negative
number, or it would arbitrarily remove items from the stack.

[ChangeLog][QtGui][Text] Fixed a crash bug in
QTextDocument::clearUndoRedoStacks(QTextDocument::UndoStack).

Task-number: QTBUG-69546
Change-Id: I8a93e828ec27970763a2756071fa0b01678d2dcd
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
This commit is contained in:
Eskil Abrahamsen Blomfeldt 2019-08-07 15:25:49 +02:00
parent 1880fba971
commit 79e0effead
2 changed files with 14 additions and 2 deletions

View File

@ -1103,12 +1103,11 @@ void QTextDocumentPrivate::clearUndoRedoStacks(QTextDocument::Stacks stacksToCle
bool redoCommandsAvailable = undoState != undoStack.size();
if (stacksToClear == QTextDocument::UndoStack && undoCommandsAvailable) {
for (int i = 0; i < undoState; ++i) {
QTextUndoCommand c = undoStack.at(undoState);
QTextUndoCommand c = undoStack.at(i);
if (c.command & QTextUndoCommand::Custom)
delete c.custom;
}
undoStack.remove(0, undoState);
undoStack.resize(undoStack.size() - undoState);
undoState = 0;
if (emitSignals)
emitUndoAvailable(false);

View File

@ -188,6 +188,8 @@ private slots:
void lineHeightType();
void cssLineHeightMultiplier();
void clearUndoRedoStacks();
private:
void backgroundImage_checkExpectedHtml(const QTextDocument &doc);
void buildRegExpData();
@ -3486,5 +3488,16 @@ void tst_QTextDocument::cssLineHeightMultiplier()
}
}
void tst_QTextDocument::clearUndoRedoStacks()
{
QTextDocument doc;
QTextCursor c(&doc);
c.insertText(QStringLiteral("lorem ipsum"));
QVERIFY(doc.isUndoAvailable());
doc.clearUndoRedoStacks(QTextDocument::UndoStack); // Don't crash
QVERIFY(!doc.isUndoAvailable());
}
QTEST_MAIN(tst_QTextDocument)
#include "tst_qtextdocument.moc"