DialogButtonBox: test item deletion order

Ensure that items declared before and after the control itself do not
cause heap-use-after-frees due to deletion order.

Task-number: QTBUG-100396
Pick-to: 6.2 6.3
Change-Id: I3989bf1b9fc64b4ec86f241de2cb8bcd05c2f89d
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
Mitch Curtis 2022-06-01 16:07:47 +08:00
parent ce1ec037d1
commit 73e173d73c
2 changed files with 89 additions and 0 deletions

View File

@ -497,6 +497,13 @@ QQuickDialogButtonBox::QQuickDialogButtonBox(QQuickItem *parent)
QQuickDialogButtonBox::~QQuickDialogButtonBox()
{
Q_D(QQuickDialogButtonBox);
// QQuickContainerPrivate does call this, but as our type information has already been
// destroyed by that point (since this destructor has already run), it won't call our
// implementation. So, we need to make sure our implementation is called. If we don't do this,
// the listener we installed on the contentItem won't get removed, possibly resulting in
// heap-use-after-frees.
contentItemChange(nullptr, d->contentItem);
}
/*!

View File

@ -528,4 +528,86 @@ TestCase {
control.destroy()
}
}
Component {
id: contentItemDeletionOrder1
Item {
objectName: "parentItem"
Item {
id: item
objectName: "contentItem"
}
DialogButtonBox {
objectName: "control"
contentItem: item
}
}
}
Component {
id: contentItemDeletionOrder2
Item {
objectName: "parentItem"
DialogButtonBox {
objectName: "control"
contentItem: item
}
Item {
id: item
objectName: "contentItem"
}
}
}
function test_contentItemDeletionOrder() {
var control1 = createTemporaryObject(contentItemDeletionOrder1, testCase)
verify(control1)
var control2 = createTemporaryObject(contentItemDeletionOrder2, testCase)
verify(control2)
}
Component {
id: backgroundDeletionOrder1
Item {
objectName: "parentItem"
Item {
id: item
objectName: "backgroundItem"
}
DialogButtonBox {
objectName: "control"
background: item
}
}
}
Component {
id: backgroundDeletionOrder2
Item {
objectName: "parentItem"
DialogButtonBox {
objectName: "control"
background: item
}
Item {
id: item
objectName: "backgroundItem"
}
}
}
function test_backgroundDeletionOrder() {
var control1 = createTemporaryObject(backgroundDeletionOrder1, testCase)
verify(control1)
var control2 = createTemporaryObject(backgroundDeletionOrder2, testCase)
verify(control2)
}
}