From 16d946701d7fc38fce264ffdb4d5443ffcb50514 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Fri, 23 Apr 2021 12:16:26 +0200 Subject: ScrollView: fix crash when scrolling with zero-sized item Check if a Flickable type was actually set as the contentItem before accessing the pointer. Also warn that using a type other than Flickable is not supported. Fixes: QTBUG-93039 Change-Id: I1470766c6de02b7b601edf1375791d3147f26ab5 Reviewed-by: Volker Hilsheimer (cherry picked from commit e7df2279bf5519703fd0b853abaa23947a599920) --- src/quicktemplates2/qquickscrollbar.cpp | 6 ++++++ src/quicktemplates2/qquickscrollview.cpp | 6 +++++- tests/auto/controls/data/tst_scrollview.qml | 24 ++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/quicktemplates2/qquickscrollbar.cpp b/src/quicktemplates2/qquickscrollbar.cpp index fdbd4b31..1ac4b42d 100644 --- a/src/quicktemplates2/qquickscrollbar.cpp +++ b/src/quicktemplates2/qquickscrollbar.cpp @@ -869,6 +869,9 @@ class QQuickFriendlyFlickable : public QQuickFlickable void QQuickScrollBarAttachedPrivate::scrollHorizontal() { + if (!flickable) + return; + QQuickFriendlyFlickable *f = reinterpret_cast(flickable); const qreal viewwidth = f->width(); @@ -881,6 +884,9 @@ void QQuickScrollBarAttachedPrivate::scrollHorizontal() void QQuickScrollBarAttachedPrivate::scrollVertical() { + if (!flickable) + return; + QQuickFriendlyFlickable *f = reinterpret_cast(flickable); const qreal viewheight = f->height(); diff --git a/src/quicktemplates2/qquickscrollview.cpp b/src/quicktemplates2/qquickscrollview.cpp index 387c30a5..0c9d8f3e 100644 --- a/src/quicktemplates2/qquickscrollview.cpp +++ b/src/quicktemplates2/qquickscrollview.cpp @@ -38,6 +38,7 @@ #include "qquickpane_p_p.h" #include "qquickscrollbar_p_p.h" +#include #include QT_BEGIN_NAMESPACE @@ -575,7 +576,10 @@ void QQuickScrollView::contentItemChange(QQuickItem *newItem, QQuickItem *oldIte // assume/require that it has an explicit content size assigned. d->flickableHasExplicitContentWidth = true; d->flickableHasExplicitContentHeight = true; - d->setFlickable(qobject_cast(newItem), false); + auto newItemAsFlickable = qobject_cast(newItem); + if (newItem && !newItemAsFlickable) + qmlWarning(this) << "ScrollView only supports Flickable types as its contentItem"; + d->setFlickable(newItemAsFlickable, false); } QQuickPane::contentItemChange(newItem, oldItem); } diff --git a/tests/auto/controls/data/tst_scrollview.qml b/tests/auto/controls/data/tst_scrollview.qml index 87c39509..453f7753 100644 --- a/tests/auto/controls/data/tst_scrollview.qml +++ b/tests/auto/controls/data/tst_scrollview.qml @@ -502,4 +502,28 @@ TestCase { compare(control.contentWidth, flickable.contentWidth) compare(control.contentHeight, flickable.contentHeight) } + + Component { + id: zeroSizedContentItemComponent + ScrollView { + width: 100 + height: 100 + contentItem: Item {} + } + } + + function test_zeroSizedContentItem() { + ignoreWarning(/ScrollView only supports Flickable types as its contentItem/) + let control = createTemporaryObject(zeroSizedContentItemComponent, testCase) + verify(control) + + let verticalScrollBar = control.ScrollBar.vertical + verify(verticalScrollBar) + // Scrolling a ScrollView with a zero-sized contentItem shouldn't crash. + mouseDrag(verticalScrollBar, verticalScrollBar.width / 2, verticalScrollBar.height / 2, 0, 50) + + let horizontalScrollBar = control.ScrollBar.horizontal + verify(verticalScrollBar) + mouseDrag(horizontalScrollBar, horizontalScrollBar.width / 2, horizontalScrollBar.height / 2, 50, 0) + } } -- cgit v1.2.3