summaryrefslogtreecommitdiffstats
path: root/tests/auto/widgets/kernel
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@qt.io>2023-01-12 16:25:31 +0100
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2023-01-13 14:38:16 +0100
commitc3a5fe2fd7a1b8a6b6133c938ffe6b3f30181bf0 (patch)
treed02d98633c4ce910a8653c6a4aefbe6a719e292a /tests/auto/widgets/kernel
parent4e4cd7416af3f84e6a7c7dee03a2e50864e9cacc (diff)
QFormLayout: don't access out-of-bounds layout data
When rows are hidden (implicitly or explicitly), then their layout data does not get fully updated. If rows get hidden after the layout data has been calculated once, then we must make sure that their indices are reset. Otherwise we might access array indices that are out of bounds when the layout data structure gets resized to fit only visible rows. For good measure, skip entirely over hidden rows when accessing the layout data when arranging the widget. Fixes: QTBUG-109237 Pick-to: 6.5 6.4 Change-Id: I4d6943b6a110edb61f60ce78d31f0fc64b5cc03d Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
Diffstat (limited to 'tests/auto/widgets/kernel')
-rw-r--r--tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp44
1 files changed, 44 insertions, 0 deletions
diff --git a/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp b/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp
index 33e6bd64db..44b716bb34 100644
--- a/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp
+++ b/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp
@@ -112,6 +112,7 @@ private slots:
void setLayout();
void hideShowRow();
void showWithHiddenRow();
+ void hiddenRowAndStretch();
/*
QLayoutItem *itemAt(int row, ItemRole role) const;
@@ -1253,6 +1254,49 @@ void tst_QFormLayout::showWithHiddenRow()
topLevel.show();
}
+/*
+ Test that hiding rows does not leave outdated layout data behind
+ in hidden items that results in out-of-bounds array access. See
+ QTBUG-109237.
+*/
+void tst_QFormLayout::hiddenRowAndStretch()
+{
+ QWidget topLevel;
+ QFormLayout layout;
+ layout.setRowWrapPolicy(QFormLayout::WrapAllRows);
+
+ // We need our own stretcher item so that QFormLayout doesn't insert
+ // it's own, as that would grow the size of the layout data array again.
+ QSpacerItem *stretch = new QSpacerItem(100, 100, QSizePolicy::Expanding, QSizePolicy::Expanding);
+ layout.setItem(0, QFormLayout::FieldRole, stretch);
+
+ QLabel *lastLabel = nullptr;
+ QLineEdit *lastField = nullptr;
+ for (int row = 1; row < 4; ++row) {
+ QLabel *label = new QLabel(QString("Label %1").arg(row));
+ label->setWordWrap(true);
+ QLineEdit *field = new QLineEdit;
+ layout.setWidget(row, QFormLayout::LabelRole, label);
+ layout.setWidget(row, QFormLayout::FieldRole, field);
+ if (row == 3) {
+ lastLabel = label;
+ lastField = field;
+ }
+ }
+
+ Q_ASSERT(lastLabel);
+ Q_ASSERT(lastField);
+
+ topLevel.setLayout(&layout);
+ topLevel.sizeHint();
+
+ lastLabel->setVisible(false);
+ lastField->setVisible(false);
+
+ // should not assert here
+ topLevel.show();
+}
+
void tst_QFormLayout::itemAt()
{
QWidget topLevel;