diff --git a/frameworks/qt5base/Makefile b/frameworks/qt5base/Makefile index 0511288..9ead498 100644 --- a/frameworks/qt5base/Makefile +++ b/frameworks/qt5base/Makefile @@ -12,13 +12,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=qt5base -PKG_VERSION:=5.15.0 +PKG_VERSION:=5.15.2 PKG_RELEASE:=1 -PKG_HASH:=bc9a21e9f6fff9629019fdf9f989f064751d5073c3a28dc596def92f4d4275c6 +PKG_HASH:=909fad2591ee367993a75d7e2ea50ad4db332f05e1c38dd7a5a274e156a4e0f8 PKG_SYS_NAME:=qtbase-everywhere-src-$(PKG_VERSION) PKG_SOURCE:=$(PKG_SYS_NAME).tar.xz -PKG_SOURCE_URL:=https://download.qt.io/official_releases/qt/$(basename $(PKG_VERSION))/$(PKG_VERSION)/submodules +PKG_SOURCE_URL:=https://download.qt.io/archive/qt/$(basename $(PKG_VERSION))/$(PKG_VERSION)/submodules PKG_BUILD_DIR=$(BUILD_DIR)/$(PKG_SYS_NAME) HOST_BUILD_DIR=$(BUILD_DIR)/host/$(PKG_SYS_NAME) @@ -377,7 +377,7 @@ define Build/Configure --opengles3=no \ --egl=no \ --xcb-xlib=no \ - --qpa=$(if $(CONFIG_PACKAGE_qt5base-plugin-platforms-linuxfb),linuxfb,) \ + --qpa=$(if $(CONFIG_PACKAGE_qt5base-plugin-platforms-linuxfb),linuxfb,no) \ --directfb=no \ --eglfs=no \ --gbm=no \ diff --git a/frameworks/qt5base/patches/100-xcb_screens_uaf.patch b/frameworks/qt5base/patches/100-xcb_screens_uaf.patch new file mode 100644 index 0000000..600e10d --- /dev/null +++ b/frameworks/qt5base/patches/100-xcb_screens_uaf.patch @@ -0,0 +1,26 @@ +Description: Avoid use-after-free in QXcbConnection::initializeScreens() +Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=86b8c5c3f32c2457 +Last-Update: 2020-11-23 + +--- a/src/plugins/platforms/xcb/qxcbconnection_screens.cpp ++++ b/src/plugins/platforms/xcb/qxcbconnection_screens.cpp +@@ -290,6 +290,8 @@ void QXcbConnection::initializeScreens() + // RRGetScreenResources in this case. + auto resources_current = Q_XCB_REPLY(xcb_randr_get_screen_resources_current, + xcb_connection(), xcbScreen->root); ++ decltype(Q_XCB_REPLY(xcb_randr_get_screen_resources, ++ xcb_connection(), xcbScreen->root)) resources; + if (!resources_current) { + qWarning("failed to get the current screen resources"); + } else { +@@ -300,8 +302,8 @@ void QXcbConnection::initializeScreens() + timestamp = resources_current->config_timestamp; + outputs = xcb_randr_get_screen_resources_current_outputs(resources_current.get()); + } else { +- auto resources = Q_XCB_REPLY(xcb_randr_get_screen_resources, +- xcb_connection(), xcbScreen->root); ++ resources = Q_XCB_REPLY(xcb_randr_get_screen_resources, ++ xcb_connection(), xcbScreen->root); + if (!resources) { + qWarning("failed to get the screen resources"); + } else { diff --git a/frameworks/qt5base/patches/101-qnam_connect_memory_leak.patch b/frameworks/qt5base/patches/101-qnam_connect_memory_leak.patch new file mode 100644 index 0000000..f16b2bc --- /dev/null +++ b/frameworks/qt5base/patches/101-qnam_connect_memory_leak.patch @@ -0,0 +1,25 @@ +Description: QNAM: work around QObject finicky orphan cleanup details +Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=0807f16eb407eaf8 +Last-Update: 2021-01-26 + +--- a/src/network/access/qnetworkreplyhttpimpl.cpp ++++ b/src/network/access/qnetworkreplyhttpimpl.cpp +@@ -808,7 +808,17 @@ void QNetworkReplyHttpImplPrivate::postR + + // For the synchronous HTTP, this is the normal way the delegate gets deleted + // For the asynchronous HTTP this is a safety measure, the delegate deletes itself when HTTP is finished +- QObject::connect(thread, SIGNAL(finished()), delegate, SLOT(deleteLater())); ++ QMetaObject::Connection threadFinishedConnection = ++ QObject::connect(thread, SIGNAL(finished()), delegate, SLOT(deleteLater())); ++ ++ // QTBUG-88063: When 'delegate' is deleted the connection will be added to 'thread''s orphaned ++ // connections list. This orphaned list will be cleaned up next time 'thread' emits a signal, ++ // unfortunately that's the finished signal. It leads to a soft-leak so we do this to disconnect ++ // it on deletion so that it cleans up the orphan immediately. ++ QObject::connect(delegate, &QObject::destroyed, delegate, [threadFinishedConnection]() { ++ if (bool(threadFinishedConnection)) ++ QObject::disconnect(threadFinishedConnection); ++ }); + + // Set the properties it needs + delegate->httpRequest = httpRequest; diff --git a/frameworks/qt5base/patches/102-gcc_11_limits.patch b/frameworks/qt5base/patches/102-gcc_11_limits.patch new file mode 100644 index 0000000..9d39131 --- /dev/null +++ b/frameworks/qt5base/patches/102-gcc_11_limits.patch @@ -0,0 +1,38 @@ +Description: include to fix some GCC 11 build issues +Origin: upstream, commits: + https://code.qt.io/cgit/qt/qtbase.git/commit/?id=813a928c7c3cf986 + https://code.qt.io/cgit/qt/qtbase.git/commit/?id=9c56d4da2ff631a8 +Last-Update: 2021-01-26 + +--- a/src/corelib/global/qendian.h ++++ b/src/corelib/global/qendian.h +@@ -44,6 +44,8 @@ + #include + #include + ++#include ++ + // include stdlib.h and hope that it defines __GLIBC__ for glibc-based systems + #include + #include +--- a/src/corelib/global/qfloat16.h ++++ b/src/corelib/global/qfloat16.h +@@ -43,6 +43,7 @@ + + #include + #include ++#include + #include + + #if defined(QT_COMPILER_SUPPORTS_F16C) && defined(__AVX2__) && !defined(__F16C__) +--- a/src/corelib/text/qbytearraymatcher.h ++++ b/src/corelib/text/qbytearraymatcher.h +@@ -42,6 +42,8 @@ + + #include + ++#include ++ + QT_BEGIN_NAMESPACE + + diff --git a/frameworks/qt5base/patches/103-qiodevice_readline_memory.patch b/frameworks/qt5base/patches/103-qiodevice_readline_memory.patch new file mode 100644 index 0000000..4ce27af --- /dev/null +++ b/frameworks/qt5base/patches/103-qiodevice_readline_memory.patch @@ -0,0 +1,21 @@ +Description: fix allocated memory of QByteArray returned by QIODevice::readLine +Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=6485b6d45ad165cf +Last-Update: 2021-02-20 + +--- a/src/corelib/io/qiodevice.cpp ++++ b/src/corelib/io/qiodevice.cpp +@@ -1480,10 +1480,12 @@ QByteArray QIODevice::readLine(qint64 ma + } else + readBytes = readLine(result.data(), result.size()); + +- if (readBytes <= 0) ++ if (readBytes <= 0) { + result.clear(); +- else ++ } else { + result.resize(readBytes); ++ result.squeeze(); ++ } + + return result; + } diff --git a/frameworks/qt5base/patches/104-mime_globs.patch b/frameworks/qt5base/patches/104-mime_globs.patch new file mode 100644 index 0000000..1c66eba --- /dev/null +++ b/frameworks/qt5base/patches/104-mime_globs.patch @@ -0,0 +1,51 @@ +Description: adjust QMimeDatabase implementation + When multiple globs match, and the result from magic sniffing is + unrelated to any of those globs, globs have priority and one of them + should be picked up. +Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=0cbbba2aa5b47224 +Last-Update: 2021-06-12 + +--- a/src/corelib/mimetypes/qmimedatabase.cpp ++++ b/src/corelib/mimetypes/qmimedatabase.cpp +@@ -389,20 +389,23 @@ QMimeType QMimeDatabasePrivate::mimeType + // Disambiguate conflicting extensions (if magic matching found something) + if (candidateByData.isValid() && magicAccuracy > 0) { + const QString sniffedMime = candidateByData.name(); +- // If the sniffedMime matches a glob match, use it ++ // If the sniffedMime matches a highest-weight glob match, use it + if (candidatesByName.m_matchingMimeTypes.contains(sniffedMime)) { + *accuracyPtr = 100; + return candidateByData; + } +- for (const QString &m : qAsConst(candidatesByName.m_matchingMimeTypes)) { ++ for (const QString &m : qAsConst(candidatesByName.m_allMatchingMimeTypes)) { + if (inherits(m, sniffedMime)) { + // We have magic + pattern pointing to this, so it's a pretty good match + *accuracyPtr = 100; + return mimeTypeForName(m); + } + } +- *accuracyPtr = magicAccuracy; +- return candidateByData; ++ if (candidatesByName.m_allMatchingMimeTypes.isEmpty()) { ++ // No glob, use magic ++ *accuracyPtr = magicAccuracy; ++ return candidateByData; ++ } + } + } + +--- a/src/corelib/mimetypes/qmimeglobpattern.cpp ++++ b/src/corelib/mimetypes/qmimeglobpattern.cpp +@@ -83,7 +83,10 @@ void QMimeGlobMatchResult::addMatch(cons + } + if (!m_matchingMimeTypes.contains(mimeType)) { + m_matchingMimeTypes.append(mimeType); +- m_allMatchingMimeTypes.append(mimeType); ++ if (replace) ++ m_allMatchingMimeTypes.prepend(mimeType); // highest-weight first ++ else ++ m_allMatchingMimeTypes.append(mimeType); + m_knownSuffixLength = knownSuffixLength; + } + } diff --git a/frameworks/qt5base/patches/105-fix-invalid-pointer-return-with-QGridLayout.patch b/frameworks/qt5base/patches/105-fix-invalid-pointer-return-with-QGridLayout.patch new file mode 100644 index 0000000..9eac33d --- /dev/null +++ b/frameworks/qt5base/patches/105-fix-invalid-pointer-return-with-QGridLayout.patch @@ -0,0 +1,113 @@ +From c47bb4478a4c3a29c0505d7d89755f40601b326f Mon Sep 17 00:00:00 2001 +From: Zhang Yu +Date: Mon, 22 Feb 2021 09:25:01 +0800 +Subject: [PATCH] Fix invalid pointer return with QGridLayout::itemAt(-1) + +QGridLayout::takeAt() and QLayoutItem *itemAt() only check the upper bound. +If the index < 0, these function will return invalid pointer. + +Fixes: QTBUG-91261 +Pick-to: 5.15 6.0 6.1 +Change-Id: Idfb9fb6228b9707f817353b04974da16205a835c +Reviewed-by: Giuseppe D'Angelo +--- + +diff --git a/src/widgets/kernel/qgridlayout.cpp b/src/widgets/kernel/qgridlayout.cpp +index 121bae0..336a68c 100644 +--- a/src/widgets/kernel/qgridlayout.cpp ++++ b/src/widgets/kernel/qgridlayout.cpp +@@ -149,14 +149,14 @@ + QRect cellRect(int row, int col) const; + + inline QLayoutItem *itemAt(int index) const { +- if (index < things.count()) ++ if (index >= 0 && index < things.count()) + return things.at(index)->item(); + else + return nullptr; + } + inline QLayoutItem *takeAt(int index) { + Q_Q(QGridLayout); +- if (index < things.count()) { ++ if (index >= 0 && index < things.count()) { + if (QGridBox *b = things.takeAt(index)) { + QLayoutItem *item = b->takeItem(); + if (QLayout *l = item->layout()) { +@@ -184,7 +184,7 @@ + } + + void getItemPosition(int index, int *row, int *column, int *rowSpan, int *columnSpan) const { +- if (index < things.count()) { ++ if (index >= 0 && index < things.count()) { + const QGridBox *b = things.at(index); + int toRow = b->toRow(rr); + int toCol = b->toCol(cc); +diff --git a/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp b/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp +index e3bd1d1..2cf2462 100644 +--- a/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp ++++ b/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp +@@ -75,6 +75,7 @@ + void taskQTBUG_40609_addingWidgetToItsOwnLayout(); + void taskQTBUG_40609_addingLayoutToItself(); + void taskQTBUG_52357_spacingWhenItemIsHidden(); ++ void taskQTBUG_91261_itemIndexRange(); + void replaceWidget(); + void dontCrashWhenExtendsToEnd(); + }; +@@ -1666,6 +1667,56 @@ + QTRY_COMPARE_WITH_TIMEOUT(tempWidth, button1.width() + button3.width() + layout.spacing(), 1000); + } + ++void tst_QGridLayout::taskQTBUG_91261_itemIndexRange() ++{ ++ QWidget widget; ++ QGridLayout lay(&widget); ++ QPushButton *btn = new QPushButton(&widget); ++ lay.addWidget(btn, 0, 0); ++ ++ { ++ auto ptr = lay.itemAt(-1); ++ QCOMPARE(ptr, nullptr); ++ ++ ptr = lay.itemAt(0); ++ QCOMPARE(ptr->widget(), btn); ++ ++ ptr = lay.itemAt(1); ++ QCOMPARE(ptr, nullptr); ++ } ++ ++ { ++ int row = -1; ++ int column = -1; ++ int rowSpan; ++ int columnSpan; ++ ++ lay.getItemPosition(-1, &row, &column, &rowSpan, &columnSpan); ++ QCOMPARE(row, -1); ++ QCOMPARE(column, -1); ++ ++ lay.getItemPosition(1, &row, &column, &rowSpan, &columnSpan); ++ QCOMPARE(row, -1); ++ QCOMPARE(column, -1); ++ ++ lay.getItemPosition(0, &row, &column, &rowSpan, &columnSpan); ++ QCOMPARE(row, 0); ++ QCOMPARE(column, 0); ++ } ++ ++ { ++ auto ptr = lay.takeAt(-1); ++ QCOMPARE(ptr, nullptr); ++ ++ ptr = lay.takeAt(1); ++ QCOMPARE(ptr, nullptr); ++ ++ ptr = lay.takeAt(0); ++ QCOMPARE(ptr->widget(), btn); ++ delete ptr; ++ } ++} ++ + void tst_QGridLayout::replaceWidget() + { + QWidget wdg; diff --git a/frameworks/qt5base/patches/106-fix-misplacement-of-placeholder-text-in-QLineEdit.patch b/frameworks/qt5base/patches/106-fix-misplacement-of-placeholder-text-in-QLineEdit.patch new file mode 100644 index 0000000..3a14d54 --- /dev/null +++ b/frameworks/qt5base/patches/106-fix-misplacement-of-placeholder-text-in-QLineEdit.patch @@ -0,0 +1,53 @@ +Description: fix misplacement of placeholder text in QLineEdit with RTL content + The placeholder text was rendered in the wrong position after clicking + on the clear button in a QLineEdit with right-to-left content. The + button was still taking up space while it was fading out, so the first + paintEvent rendered the placeholder with space reserved for the clear + button. Once the button gets hidden, no new update was issued, so + garbage was left behind. + . + Fix this by not giving a fading-out clear button any margin space. The + result of this is that the placeholder text is visible underneath the + fading-out clear button. This is preferable to the placeholder text + being first rendered next to the fading-out clear button, and then + popping to the edge when the clear button is hidden (which would have + been the result of issuing a complete update for the line edit at the + end of the fade-out animation). +Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=dc794f7622bc00f7 +Last-Update: 2021-06-16 + +--- a/src/widgets/widgets/qlineedit_p.cpp ++++ b/src/widgets/widgets/qlineedit_p.cpp +@@ -664,10 +664,18 @@ static int effectiveTextMargin(int defau + if (widgets.empty()) + return defaultMargin; + +- return defaultMargin + (parameters.margin + parameters.widgetWidth) * +- int(std::count_if(widgets.begin(), widgets.end(), ++ const auto visibleSideWidgetCount = std::count_if(widgets.begin(), widgets.end(), + [](const QLineEditPrivate::SideWidgetEntry &e) { +- return e.widget->isVisibleTo(e.widget->parentWidget()); })); ++#if QT_CONFIG(animation) ++ // a button that's fading out doesn't get any space ++ if (auto* iconButton = qobject_cast(e.widget)) ++ return iconButton->needsSpace(); ++ ++#endif ++ return e.widget->isVisibleTo(e.widget->parentWidget()); ++ }); ++ ++ return defaultMargin + (parameters.margin + parameters.widgetWidth) * visibleSideWidgetCount; + } + + QMargins QLineEditPrivate::effectiveTextMargins() const +--- a/src/widgets/widgets/qlineedit_p.h ++++ b/src/widgets/widgets/qlineedit_p.h +@@ -95,6 +95,8 @@ public: + + bool shouldHideWithText() const; + void setHideWithText(bool hide); ++ // m_wasHidden is true unless the button is fading out ++ bool needsSpace() const { return m_wasHidden; } + #endif + + protected: diff --git a/frameworks/qt5base/patches/107-fusion_checkable_qpushbutton.patch b/frameworks/qt5base/patches/107-fusion_checkable_qpushbutton.patch new file mode 100644 index 0000000..ae284f4 --- /dev/null +++ b/frameworks/qt5base/patches/107-fusion_checkable_qpushbutton.patch @@ -0,0 +1,27 @@ +Description: QPushButton/fusion style: don't ignore QIcon::On icon + The fusion style did ignore the QIcon::On icon because it reset + State_On to avoid the visual shift of a pressed button. + But it's not needed to reset this flag - the shift does not happen + because the fusion style does return 0 as offset for + PM_ButtonShiftHorizontal/PM_ButtonShiftVertical so no shifting will + happen. +Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=e9ccdf4d84157173 +Last-Update: 2021-08-10 + +--- a/src/widgets/styles/qfusionstyle.cpp ++++ b/src/widgets/styles/qfusionstyle.cpp +@@ -1771,14 +1771,6 @@ void QFusionStyle::drawControl(ControlEl + proxy()->drawControl(CE_PushButtonLabel, &subopt, painter, widget); + } + break; +- case CE_PushButtonLabel: +- if (const QStyleOptionButton *button = qstyleoption_cast(option)) { +- QStyleOptionButton b(*button); +- // no PM_ButtonShiftHorizontal and PM_ButtonShiftVertical for fusion style +- b.state &= ~(State_On | State_Sunken); +- QCommonStyle::drawControl(element, &b, painter, widget); +- } +- break; + case CE_MenuBarEmptyArea: + painter->save(); + { diff --git a/frameworks/qt5base/patches/108-mysql_remove_version_checks.patch b/frameworks/qt5base/patches/108-mysql_remove_version_checks.patch new file mode 100644 index 0000000..40b7f1d --- /dev/null +++ b/frameworks/qt5base/patches/108-mysql_remove_version_checks.patch @@ -0,0 +1,44 @@ +Description: remove the version number checks in favor of actual functionality + MariaDB library version 3.2 no longer returns the server version in the + 10.x range but the library version itself, which is lower than 4.x. That + meant we concluded the server did not support prepared statements. + . + And because of the lack of prepared statements, all QDateTime + conversions failed, because of the timezone. I don't know if this was + intended or what, but it's a side issue. +Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=211369133cf40b2f +Last-Update: 2021-08-10 + +--- a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp ++++ b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp +@@ -158,6 +158,20 @@ static inline QVariant qDateTimeFromStri + #endif + } + ++// check if this client and server version of MySQL/MariaDB support prepared statements ++static inline bool checkPreparedQueries(MYSQL *mysql) ++{ ++ std::unique_ptr stmt(mysql_stmt_init(mysql), &mysql_stmt_close); ++ if (!stmt) ++ return false; ++ ++ static const char dummyQuery[] = "SELECT ? + ?"; ++ if (mysql_stmt_prepare(stmt.get(), dummyQuery, sizeof(dummyQuery) - 1)) ++ return false; ++ ++ return mysql_stmt_param_count(stmt.get()) == 2; ++} ++ + class QMYSQLResultPrivate; + + class QMYSQLResult : public QSqlResult +@@ -1371,8 +1385,7 @@ bool QMYSQLDriver::open(const QString& d + } + #endif // MYSQL_VERSION_ID >= 50007 + +- d->preparedQuerysEnabled = mysql_get_client_version() >= 40108 +- && mysql_get_server_version(d->mysql) >= 40100; ++ d->preparedQuerysEnabled = checkPreparedQueries(d->mysql); + + #if QT_CONFIG(thread) + mysql_thread_init(); diff --git a/frameworks/qt5base/patches/109-full_width_selection_rtl.patch b/frameworks/qt5base/patches/109-full_width_selection_rtl.patch new file mode 100644 index 0000000..99e042c --- /dev/null +++ b/frameworks/qt5base/patches/109-full_width_selection_rtl.patch @@ -0,0 +1,33 @@ +Description: fix QTextFormat::FullWidthSelection for right-to-left text layouts + Using the QTextFormat::FullWidthSelection property to select a line + would previously not take into account right-to-left text layouts. + . + With this patch, the whole line should now be drawn correctly for both + left-to-right, and right-to-left layouts. +Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=a7894855f2f59028 +Last-Update: 2021-08-15 + +--- a/src/gui/text/qtextlayout.cpp ++++ b/src/gui/text/qtextlayout.cpp +@@ -1169,10 +1169,17 @@ void QTextLayout::draw(QPainter *p, cons + QRectF fullLineRect(tl.rect()); + fullLineRect.translate(position); + fullLineRect.setRight(QFIXED_MAX); +- if (!selectionEndInLine) +- region.addRect(clipIfValid(QRectF(lineRect.topRight(), fullLineRect.bottomRight()), clip)); +- if (!selectionStartInLine) +- region.addRect(clipIfValid(QRectF(fullLineRect.topLeft(), lineRect.bottomLeft()), clip)); ++ ++ const bool rightToLeft = d->isRightToLeft(); ++ ++ if (!selectionEndInLine) { ++ region.addRect(clipIfValid(rightToLeft ? QRectF(fullLineRect.topLeft(), lineRect.bottomLeft()) ++ : QRectF(lineRect.topRight(), fullLineRect.bottomRight()), clip)); ++ } ++ if (!selectionStartInLine) { ++ region.addRect(clipIfValid(rightToLeft ? QRectF(lineRect.topRight(), fullLineRect.bottomRight()) ++ : QRectF(fullLineRect.topLeft(), lineRect.bottomLeft()), clip)); ++ } + } else if (!selectionEndInLine + && isLastLineInBlock + &&!(d->option.flags() & QTextOption::ShowLineAndParagraphSeparators)) { diff --git a/frameworks/qt5base/patches/110-xcb_add_a_timeout_control_when_reading_INCR_property.patch b/frameworks/qt5base/patches/110-xcb_add_a_timeout_control_when_reading_INCR_property.patch new file mode 100644 index 0000000..5b090a6 --- /dev/null +++ b/frameworks/qt5base/patches/110-xcb_add_a_timeout_control_when_reading_INCR_property.patch @@ -0,0 +1,53 @@ +From 02248eea5562c1df39ee23f195011afacc6759b0 Mon Sep 17 00:00:00 2001 +From: Liang Qi +Date: Wed, 7 Jul 2021 13:19:14 +0200 +Subject: [PATCH] xcb: add a timeout control when reading INCR property +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +For the first call of QXcbClipboard::clipboardReadProperty() +inside of clipboardReadIncrementalProperty() in getSelection(), +it will get a XCB_NONE reply before the contents arrived via +property change. Then we give a chance to read more. + +Manually tested with following setups: +* examples/widgets/mainwindows/application with gvim(gtk3) +* examples/widgets/widgets/imageviewer with GIMP 2.10.18(based on +gtk2) and GIMP 2.99.6(based on gtk3 via flatpak) + +Fixes: QTBUG-56595 +Pick-to: 5.12 5.15 6.1 6.2 +Done-With: JiDe Zhang +Change-Id: Ib45f08464d39ad79137b1da99808c89b7dca2d08 +Reviewed-by: JiDe Zhang +Reviewed-by: Tor Arne Vestbø +--- + src/plugins/platforms/xcb/qxcbclipboard.cpp | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/src/plugins/platforms/xcb/qxcbclipboard.cpp ++++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp +@@ -829,6 +829,8 @@ QByteArray QXcbClipboard::clipboardReadI + alloc_error = buf.size() != nbytes+1; + } + ++ QElapsedTimer timer; ++ timer.start(); + for (;;) { + connection()->flush(); + xcb_generic_event_t *ge = waitForClipboardEvent(win, XCB_PROPERTY_NOTIFY); +@@ -864,9 +866,11 @@ QByteArray QXcbClipboard::clipboardReadI + tmp_buf.resize(0); + offset += length; + } +- } else { +- break; + } ++ ++ const auto elapsed = timer.elapsed(); ++ if (elapsed > clipboard_timeout) ++ break; + } + + // timed out ... create a new requestor window, otherwise the requestor diff --git a/frameworks/qt5base/patches/111-fix_recursion_crash.patch b/frameworks/qt5base/patches/111-fix_recursion_crash.patch new file mode 100644 index 0000000..0a1a3d5 --- /dev/null +++ b/frameworks/qt5base/patches/111-fix_recursion_crash.patch @@ -0,0 +1,56 @@ +Description: fix recursion crash when calling setStyleSheet with qproperty-styleSheet + When calling setStyleSheet with property qproperty-styleSheet, + QStyleSheetStyle::polish will call QStyleSheetStyle::setProperties, + and then QStyleSheetStyle::setProperties goes on to call setProperty. + Because there is property qproperty-styleSheet, it will update + stylesheet by calling QStyleSheetStyle::polish. + This causes the recursive call to crash. +Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=e9cdcc7cb314586a +Last-Update: 2021-11-13 + +--- a/src/widgets/styles/qstylesheetstyle.cpp ++++ b/src/widgets/styles/qstylesheetstyle.cpp +@@ -2626,6 +2626,9 @@ void QStyleSheetStyle::setProperties(QWi + default: v = decl.d->values.at(0).variant; break; + } + ++ if (propertyL1 == QByteArray("styleSheet") && value == v) ++ continue; ++ + w->setProperty(propertyL1, v); + } + } +--- a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp ++++ b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp +@@ -94,6 +94,7 @@ private slots: + void layoutSpacing(); + #endif + void qproperty(); ++ void qproperty_styleSheet(); + void palettePropagation_data(); + void palettePropagation(); + void fontPropagation_data(); +@@ -677,6 +678,23 @@ void tst_QStyleSheetStyle::qproperty() + QCOMPARE(pb.isChecked(), false); + } + ++void tst_QStyleSheetStyle::qproperty_styleSheet() ++{ ++ QWidget w; ++ auto checkBox = new QCheckBox("check", &w); ++ QString sheet = R"(QCheckBox { qproperty-styleSheet: "QCheckBox { qproperty-text: foobar; }"; })"; ++ ++ QVERIFY(w.property("styleSheet").toString().isEmpty()); ++ ++ w.setStyleSheet(sheet); ++ QCOMPARE(checkBox->text(), "check"); ++ ++ //recursion crash ++ w.ensurePolished(); ++ QCOMPARE(w.property("styleSheet").toString(), sheet); ++ QCOMPARE(checkBox->text(), "foobar"); ++} ++ + namespace ns { + class PushButton1 : public QPushButton { + Q_OBJECT diff --git a/frameworks/qt5base/patches/112-mysql_field_readonly.patch b/frameworks/qt5base/patches/112-mysql_field_readonly.patch new file mode 100644 index 0000000..c33b752 --- /dev/null +++ b/frameworks/qt5base/patches/112-mysql_field_readonly.patch @@ -0,0 +1,80 @@ +Description: treat the MYSQL_FIELD as read-only + The MariaDB-connector-c version 3.2 and MariaDB server version 10.6 + cooperate to avoid re-transferring the query metadata, so the fact that + we were modifying it was causing it to improperly decode the DATETIME + data types into string, as we had asked. We ended up with a 7-byte + string that was actually the date binary-encoded. +Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=549ee216fd5bf2b3 +Last-Update: 2021-11-13 + +--- a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp ++++ b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp +@@ -223,7 +223,7 @@ public: + struct QMyField + { + char *outField = nullptr; +- MYSQL_FIELD *myField = nullptr; ++ const MYSQL_FIELD *myField = nullptr; + QMetaType::Type type = QMetaType::UnknownType; + my_bool nullIndicator = false; + ulong bufLength = 0ul; +@@ -361,11 +361,10 @@ static bool qIsInteger(int t) + void QMYSQLResultPrivate::bindBlobs() + { + int i; +- MYSQL_FIELD *fieldInfo; + MYSQL_BIND *bind; + + for(i = 0; i < fields.count(); ++i) { +- fieldInfo = fields.at(i).myField; ++ const MYSQL_FIELD *fieldInfo = fields.at(i).myField; + if (qIsBlob(inBinds[i].buffer_type) && meta && fieldInfo) { + bind = &inBinds[i]; + bind->buffer_length = fieldInfo->max_length; +@@ -392,35 +391,34 @@ bool QMYSQLResultPrivate::bindInValues() + inBinds = new MYSQL_BIND[fields.size()]; + memset(inBinds, 0, fields.size() * sizeof(MYSQL_BIND)); + +- MYSQL_FIELD *fieldInfo; ++ const MYSQL_FIELD *fieldInfo; + + while((fieldInfo = mysql_fetch_field(meta))) { ++ MYSQL_BIND *bind = &inBinds[i]; ++ + QMyField &f = fields[i]; + f.myField = fieldInfo; +- ++ bind->buffer_length = f.bufLength = fieldInfo->length + 1; ++ bind->buffer_type = fieldInfo->type; + f.type = qDecodeMYSQLType(fieldInfo->type, fieldInfo->flags); + if (qIsBlob(fieldInfo->type)) { + // the size of a blob-field is available as soon as we call + // mysql_stmt_store_result() + // after mysql_stmt_exec() in QMYSQLResult::exec() +- fieldInfo->length = 0; ++ bind->buffer_length = f.bufLength = 0; + hasBlobs = true; + } else if (qIsInteger(f.type)) { +- fieldInfo->length = 8; ++ bind->buffer_length = f.bufLength = 8; + } else { +- fieldInfo->type = MYSQL_TYPE_STRING; ++ bind->buffer_type = MYSQL_TYPE_STRING; + } +- bind = &inBinds[i]; +- field = new char[fieldInfo->length + 1]; +- memset(field, 0, fieldInfo->length + 1); + +- bind->buffer_type = fieldInfo->type; +- bind->buffer = field; +- bind->buffer_length = f.bufLength = fieldInfo->length + 1; + bind->is_null = &f.nullIndicator; + bind->length = &f.bufLength; + bind->is_unsigned = fieldInfo->flags & UNSIGNED_FLAG ? 1 : 0; +- f.outField=field; ++ ++ char *field = new char[bind->buffer_length + 1]{}; ++ bind->buffer = f.outField = field; + + ++i; + } diff --git a/frameworks/qt5base/patches/113-CVE-2021-38593.patch b/frameworks/qt5base/patches/113-CVE-2021-38593.patch new file mode 100644 index 0000000..6f5d939 --- /dev/null +++ b/frameworks/qt5base/patches/113-CVE-2021-38593.patch @@ -0,0 +1,84 @@ +Description: avoid processing-intensive painting of high number of tiny dashes + When stroking a dashed path, an unnecessary amount of processing would + be spent if there is a huge number of dashes visible, e.g. because of + scaling. Since the dashes are too small to be individually visible + anyway, just replace with a semi-transparent solid line for such + cases. +Origin: upstream, commits: + https://code.qt.io/cgit/qt/qtbase.git/commit/?id=f4d791b330d02777 + https://code.qt.io/cgit/qt/qtbase.git/commit/?id=6b400e3147dcfd8c + https://code.qt.io/cgit/qt/qtbase.git/commit/?id=84aba80944a2e1c3 + https://code.qt.io/cgit/qt/qtbase.git/commit/?id=cca8ed0547405b1c +Last-Update: 2021-11-27 + +--- a/src/gui/painting/qpaintengineex.cpp ++++ b/src/gui/painting/qpaintengineex.cpp +@@ -385,10 +385,10 @@ QPainterState *QPaintEngineEx::createSta + + Q_GUI_EXPORT extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp + +-void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) ++void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &inPen) + { + #ifdef QT_DEBUG_DRAW +- qDebug() << "QPaintEngineEx::stroke()" << pen; ++ qDebug() << "QPaintEngineEx::stroke()" << inPen; + #endif + + Q_D(QPaintEngineEx); +@@ -403,6 +403,38 @@ void QPaintEngineEx::stroke(const QVecto + d->stroker.setCubicToHook(qpaintengineex_cubicTo); + } + ++ QRectF clipRect; ++ QPen pen = inPen; ++ if (pen.style() > Qt::SolidLine) { ++ QRectF cpRect = path.controlPointRect(); ++ const QTransform &xf = state()->matrix; ++ if (qt_pen_is_cosmetic(pen, state()->renderHints)) { ++ clipRect = d->exDeviceRect; ++ cpRect.translate(xf.dx(), xf.dy()); ++ } else { ++ clipRect = xf.inverted().mapRect(QRectF(d->exDeviceRect)); ++ } ++ // Check to avoid generating unwieldy amount of dashes that will not be visible anyway ++ qreal pw = pen.widthF() ? pen.widthF() : 1; ++ QRectF extentRect = cpRect.adjusted(-pw, -pw, pw, pw) & clipRect; ++ qreal extent = qMax(extentRect.width(), extentRect.height()); ++ qreal patternLength = 0; ++ const QVector pattern = pen.dashPattern(); ++ const int patternSize = qMin(pattern.size(), 32); ++ for (int i = 0; i < patternSize; i++) ++ patternLength += qMax(pattern.at(i), qreal(0)); ++ patternLength *= pw; ++ if (qFuzzyIsNull(patternLength)) { ++ pen.setStyle(Qt::NoPen); ++ } else if (extent / patternLength > 10000) { ++ // approximate stream of tiny dashes with semi-transparent solid line ++ pen.setStyle(Qt::SolidLine); ++ QColor color(pen.color()); ++ color.setAlpha(color.alpha() / 2); ++ pen.setColor(color); ++ } ++ } ++ + if (!qpen_fast_equals(pen, d->strokerPen)) { + d->strokerPen = pen; + d->stroker.setJoinStyle(pen.joinStyle()); +@@ -430,14 +462,8 @@ void QPaintEngineEx::stroke(const QVecto + return; + } + +- if (pen.style() > Qt::SolidLine) { +- if (qt_pen_is_cosmetic(pen, state()->renderHints)){ +- d->activeStroker->setClipRect(d->exDeviceRect); +- } else { +- QRectF clipRect = state()->matrix.inverted().mapRect(QRectF(d->exDeviceRect)); +- d->activeStroker->setClipRect(clipRect); +- } +- } ++ if (!clipRect.isNull()) ++ d->activeStroker->setClipRect(clipRect); + + if (d->activeStroker == &d->stroker) + d->stroker.setForceOpen(path.hasExplicitOpen()); diff --git a/frameworks/qt5base/patches/114-openssl3.patch b/frameworks/qt5base/patches/114-openssl3.patch new file mode 100644 index 0000000..85d61b8 --- /dev/null +++ b/frameworks/qt5base/patches/114-openssl3.patch @@ -0,0 +1,206 @@ +Description: upstream fixes to support OpenSSL 3.0 +Origin: upstream, commits + https://code.qt.io/cgit/qt/qtbase.git/commit/?id=3186ca3e3972cf46 + https://code.qt.io/cgit/qt/qtbase.git/commit/?id=408656c6f9de326c + https://code.qt.io/cgit/qt/qtbase.git/commit/?id=ae6590e360fbb04d + and a small part of + https://code.qt.io/cgit/qt/qtbase.git/commit/?id=4c0f81490ba0c4ec +Last-Update: 2021-12-09 + +--- a/src/network/ssl/qsslcontext_openssl.cpp ++++ b/src/network/ssl/qsslcontext_openssl.cpp +@@ -409,7 +409,7 @@ init_context: + break; + case QSsl::DtlsV1_0OrLater: + minVersion = DTLS1_VERSION; +- maxVersion = DTLS_MAX_VERSION; ++ maxVersion = 0; + break; + case QSsl::DtlsV1_2: + minVersion = DTLS1_2_VERSION; +@@ -417,7 +417,7 @@ init_context: + break; + case QSsl::DtlsV1_2OrLater: + minVersion = DTLS1_2_VERSION; +- maxVersion = DTLS_MAX_VERSION; ++ maxVersion = 0; + break; + case QSsl::TlsV1_3OrLater: + #ifdef TLS1_3_VERSION +--- a/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp ++++ b/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp +@@ -59,57 +59,6 @@ + + QT_BEGIN_NAMESPACE + +-#ifdef OPENSSL_NO_DEPRECATED_3_0 +- +-static int q_DH_check(DH *dh, int *status) +-{ +- // DH_check was first deprecated in OpenSSL 3.0.0, as low-level +- // API; the EVP_PKEY family of functions was advised as an alternative. +- // As of now EVP_PKEY_params_check ends up calling ... DH_check, +- // which is good enough. +- +- Q_ASSERT(dh); +- Q_ASSERT(status); +- +- EVP_PKEY *key = q_EVP_PKEY_new(); +- if (!key) { +- qCWarning(lcSsl, "EVP_PKEY_new failed"); +- QSslSocketBackendPrivate::logAndClearErrorQueue(); +- return 0; +- } +- const auto keyDeleter = qScopeGuard([key](){ +- q_EVP_PKEY_free(key); +- }); +- if (!q_EVP_PKEY_set1_DH(key, dh)) { +- qCWarning(lcSsl, "EVP_PKEY_set1_DH failed"); +- QSslSocketBackendPrivate::logAndClearErrorQueue(); +- return 0; +- } +- +- EVP_PKEY_CTX *keyCtx = q_EVP_PKEY_CTX_new(key, nullptr); +- if (!keyCtx) { +- qCWarning(lcSsl, "EVP_PKEY_CTX_new failed"); +- QSslSocketBackendPrivate::logAndClearErrorQueue(); +- return 0; +- } +- const auto ctxDeleter = qScopeGuard([keyCtx]{ +- q_EVP_PKEY_CTX_free(keyCtx); +- }); +- +- const int result = q_EVP_PKEY_param_check(keyCtx); +- QSslSocketBackendPrivate::logAndClearErrorQueue(); +- // Note: unlike DH_check, we cannot obtain the 'status', +- // if the 'result' is 0 (actually the result is 1 only +- // if this 'status' was 0). We could probably check the +- // errors from the error queue, but it's not needed anyway +- // - see the 'isSafeDH' below, how it returns immediately +- // on 0. +- Q_UNUSED(status) +- +- return result; +-} +-#endif // OPENSSL_NO_DEPRECATED_3_0 +- + static bool isSafeDH(DH *dh) + { + int status = 0; +--- a/src/network/ssl/qsslsocket_openssl_symbols.cpp ++++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp +@@ -148,7 +148,6 @@ DEFINEFUNC(int, EVP_PKEY_up_ref, EVP_PKE + DEFINEFUNC2(EVP_PKEY_CTX *, EVP_PKEY_CTX_new, EVP_PKEY *pkey, pkey, ENGINE *e, e, return nullptr, return) + DEFINEFUNC(int, EVP_PKEY_param_check, EVP_PKEY_CTX *ctx, ctx, return 0, return) + DEFINEFUNC(void, EVP_PKEY_CTX_free, EVP_PKEY_CTX *ctx, ctx, return, return) +-DEFINEFUNC(int, EVP_PKEY_base_id, EVP_PKEY *a, a, return NID_undef, return) + DEFINEFUNC(int, RSA_bits, RSA *a, a, return 0, return) + DEFINEFUNC(int, DSA_bits, DSA *a, a, return 0, return) + DEFINEFUNC(int, OPENSSL_sk_num, OPENSSL_STACK *a, a, return -1, return) +@@ -368,7 +367,15 @@ DEFINEFUNC(const SSL_CIPHER *, SSL_get_c + DEFINEFUNC(int, SSL_version, const SSL *a, a, return 0, return) + DEFINEFUNC2(int, SSL_get_error, SSL *a, a, int b, b, return -1, return) + DEFINEFUNC(STACK_OF(X509) *, SSL_get_peer_cert_chain, SSL *a, a, return nullptr, return) ++ ++#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 ++DEFINEFUNC(X509 *, SSL_get1_peer_certificate, SSL *a, a, return nullptr, return) ++DEFINEFUNC(int, EVP_PKEY_get_base_id, const EVP_PKEY *pkey, pkey, return -1, return) ++#else + DEFINEFUNC(X509 *, SSL_get_peer_certificate, SSL *a, a, return nullptr, return) ++DEFINEFUNC(int, EVP_PKEY_base_id, EVP_PKEY *a, a, return NID_undef, return) ++#endif // OPENSSL_VERSION_MAJOR >= 3 ++ + DEFINEFUNC(long, SSL_get_verify_result, const SSL *a, a, return -1, return) + DEFINEFUNC(SSL *, SSL_new, SSL_CTX *a, a, return nullptr, return) + DEFINEFUNC(SSL_CTX *, SSL_get_SSL_CTX, SSL *a, a, return nullptr, return) +@@ -489,9 +496,7 @@ DEFINEFUNC(DH *, DH_new, DUMMYARG, DUMMY + DEFINEFUNC(void, DH_free, DH *dh, dh, return, DUMMYARG) + DEFINEFUNC3(DH *, d2i_DHparams, DH**a, a, const unsigned char **pp, pp, long length, length, return nullptr, return) + DEFINEFUNC2(int, i2d_DHparams, DH *a, a, unsigned char **p, p, return -1, return) +-#ifndef OPENSSL_NO_DEPRECATED_3_0 + DEFINEFUNC2(int, DH_check, DH *dh, dh, int *codes, codes, return 0, return) +-#endif // OPENSSL_NO_DEPRECATED_3_0 + DEFINEFUNC3(BIGNUM *, BN_bin2bn, const unsigned char *s, s, int len, len, BIGNUM *ret, ret, return nullptr, return) + + #ifndef OPENSSL_NO_EC +@@ -848,7 +853,6 @@ bool q_resolveOpenSslSymbols() + RESOLVEFUNC(EVP_PKEY_CTX_new) + RESOLVEFUNC(EVP_PKEY_param_check) + RESOLVEFUNC(EVP_PKEY_CTX_free) +- RESOLVEFUNC(EVP_PKEY_base_id) + RESOLVEFUNC(RSA_bits) + RESOLVEFUNC(OPENSSL_sk_new_null) + RESOLVEFUNC(OPENSSL_sk_push) +@@ -1073,7 +1077,15 @@ bool q_resolveOpenSslSymbols() + RESOLVEFUNC(SSL_version) + RESOLVEFUNC(SSL_get_error) + RESOLVEFUNC(SSL_get_peer_cert_chain) ++ ++#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 ++ RESOLVEFUNC(SSL_get1_peer_certificate) ++ RESOLVEFUNC(EVP_PKEY_get_base_id) ++#else + RESOLVEFUNC(SSL_get_peer_certificate) ++ RESOLVEFUNC(EVP_PKEY_base_id) ++#endif // OPENSSL_VERSION_MAJOR >= 3 ++ + RESOLVEFUNC(SSL_get_verify_result) + RESOLVEFUNC(SSL_new) + RESOLVEFUNC(SSL_get_SSL_CTX) +@@ -1172,9 +1184,7 @@ bool q_resolveOpenSslSymbols() + RESOLVEFUNC(DH_free) + RESOLVEFUNC(d2i_DHparams) + RESOLVEFUNC(i2d_DHparams) +-#ifndef OPENSSL_NO_DEPRECATED_3_0 + RESOLVEFUNC(DH_check) +-#endif // OPENSSL_NO_DEPRECATED_3_0 + RESOLVEFUNC(BN_bin2bn) + + #ifndef OPENSSL_NO_EC +--- a/src/network/ssl/qsslsocket_openssl_symbols_p.h ++++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h +@@ -236,7 +236,6 @@ Q_AUTOTEST_EXPORT int q_EVP_PKEY_up_ref( + EVP_PKEY_CTX *q_EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e); + void q_EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx); + int q_EVP_PKEY_param_check(EVP_PKEY_CTX *ctx); +-int q_EVP_PKEY_base_id(EVP_PKEY *a); + int q_RSA_bits(RSA *a); + Q_AUTOTEST_EXPORT int q_OPENSSL_sk_num(OPENSSL_STACK *a); + Q_AUTOTEST_EXPORT void q_OPENSSL_sk_pop_free(OPENSSL_STACK *a, void (*b)(void *)); +@@ -509,7 +508,6 @@ const SSL_CIPHER *q_SSL_get_current_ciph + int q_SSL_version(const SSL *a); + int q_SSL_get_error(SSL *a, int b); + STACK_OF(X509) *q_SSL_get_peer_cert_chain(SSL *a); +-X509 *q_SSL_get_peer_certificate(SSL *a); + long q_SSL_get_verify_result(const SSL *a); + SSL *q_SSL_new(SSL_CTX *a); + SSL_CTX *q_SSL_get_SSL_CTX(SSL *a); +@@ -581,10 +579,7 @@ DH *q_DH_new(); + void q_DH_free(DH *dh); + DH *q_d2i_DHparams(DH **a, const unsigned char **pp, long length); + int q_i2d_DHparams(DH *a, unsigned char **p); +- +-#ifndef OPENSSL_NO_DEPRECATED_3_0 + int q_DH_check(DH *dh, int *codes); +-#endif // OPENSSL_NO_DEPRECATED_3_0 + + BIGNUM *q_BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret); + #define q_SSL_CTX_set_tmp_dh(ctx, dh) q_SSL_CTX_ctrl((ctx), SSL_CTRL_SET_TMP_DH, 0, (char *)dh) +@@ -751,6 +746,17 @@ void *q_CRYPTO_malloc(size_t num, const + int q_SSL_CTX_get_security_level(const SSL_CTX *ctx); + void q_SSL_CTX_set_security_level(SSL_CTX *ctx, int level); + ++// Here we have the ones that make difference between OpenSSL pre/post v3: ++#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 ++X509 *q_SSL_get1_peer_certificate(SSL *a); ++#define q_SSL_get_peer_certificate q_SSL_get1_peer_certificate ++int q_EVP_PKEY_get_base_id(const EVP_PKEY *pkey); ++#define q_EVP_PKEY_base_id q_EVP_PKEY_get_base_id ++#else ++X509 *q_SSL_get_peer_certificate(SSL *a); ++int q_EVP_PKEY_base_id(EVP_PKEY *a); ++#endif // OPENSSL_VERSION_MAJOR >= 3 ++ + QT_END_NAMESPACE + + #endif diff --git a/frameworks/qt5base/patches/115-CVE-2022-25255.patch b/frameworks/qt5base/patches/115-CVE-2022-25255.patch new file mode 100644 index 0000000..764e939 --- /dev/null +++ b/frameworks/qt5base/patches/115-CVE-2022-25255.patch @@ -0,0 +1,92 @@ +Description: QProcess: ensure we don't accidentally execute something from CWD + Unless "." (or the empty string) is in $PATH, we're not supposed to find + executables in the current directory. This is how the Unix shells behave + and we match their behavior. It's also the behavior Qt had prior to 5.9 + (commit 28666d167aa8e602c0bea25ebc4d51b55005db13). On Windows, searching + the current directory is the norm, so we keep that behavior. + . + This commit does not add an explicit check for an empty return from + QStandardPaths::findExecutable(). Instead, we allow that empty string to + go all the way to execve(2), which will fail with ENOENT. We could catch + it early, before fork(2), but why add code for the error case? + . + See https://kde.org/info/security/advisory-20220131-1.txt +Origin: upstream, https://download.qt.io/official_releases/qt/5.15/CVE-2022-25255-qprocess5-15.diff +Last-Update: 2022-02-21 + +--- a/src/corelib/io/qprocess_unix.cpp ++++ b/src/corelib/io/qprocess_unix.cpp +@@ -1,7 +1,7 @@ + /**************************************************************************** + ** + ** Copyright (C) 2016 The Qt Company Ltd. +-** Copyright (C) 2016 Intel Corporation. ++** Copyright (C) 2022 Intel Corporation. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the QtCore module of the Qt Toolkit. +@@ -422,14 +422,15 @@ void QProcessPrivate::startProcess() + // Add the program name to the argument list. + argv[0] = nullptr; + if (!program.contains(QLatin1Char('/'))) { ++ // findExecutable() returns its argument if it's an absolute path, ++ // otherwise it searches $PATH; returns empty if not found (we handle ++ // that case much later) + const QString &exeFilePath = QStandardPaths::findExecutable(program); +- if (!exeFilePath.isEmpty()) { +- const QByteArray &tmp = QFile::encodeName(exeFilePath); +- argv[0] = ::strdup(tmp.constData()); +- } +- } +- if (!argv[0]) ++ const QByteArray &tmp = QFile::encodeName(exeFilePath); ++ argv[0] = ::strdup(tmp.constData()); ++ } else { + argv[0] = ::strdup(encodedProgramName.constData()); ++ } + + // Add every argument to the list + for (int i = 0; i < arguments.count(); ++i) +@@ -983,15 +984,16 @@ bool QProcessPrivate::startDetached(qint + envp = _q_dupEnvironment(environment.d.constData()->vars, &envc); + } + +- QByteArray tmp; + if (!program.contains(QLatin1Char('/'))) { ++ // findExecutable() returns its argument if it's an absolute path, ++ // otherwise it searches $PATH; returns empty if not found (we handle ++ // that case much later) + const QString &exeFilePath = QStandardPaths::findExecutable(program); +- if (!exeFilePath.isEmpty()) +- tmp = QFile::encodeName(exeFilePath); ++ const QByteArray &tmp = QFile::encodeName(exeFilePath); ++ argv[0] = ::strdup(tmp.constData()); ++ } else { ++ argv[0] = ::strdup(QFile::encodeName(program)); + } +- if (tmp.isEmpty()) +- tmp = QFile::encodeName(program); +- argv[0] = tmp.data(); + + if (envp) + qt_safe_execve(argv[0], argv, envp); +--- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp ++++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp +@@ -1449,7 +1449,7 @@ void tst_QApplication::desktopSettingsAw + { + #if QT_CONFIG(process) + QProcess testProcess; +- testProcess.start("desktopsettingsaware_helper"); ++ testProcess.start("./desktopsettingsaware_helper"); + QVERIFY2(testProcess.waitForStarted(), + qPrintable(QString::fromLatin1("Cannot start 'desktopsettingsaware_helper': %1").arg(testProcess.errorString()))); + QVERIFY(testProcess.waitForFinished(10000)); +@@ -2365,7 +2365,7 @@ void tst_QApplication::qtbug_12673() + #if QT_CONFIG(process) + QProcess testProcess; + QStringList arguments; +- testProcess.start("modal_helper", arguments); ++ testProcess.start("./modal_helper", arguments); + QVERIFY2(testProcess.waitForStarted(), + qPrintable(QString::fromLatin1("Cannot start 'modal_helper': %1").arg(testProcess.errorString()))); + QVERIFY(testProcess.waitForFinished(20000)); diff --git a/frameworks/qt5base/patches/116-fix-placement-of-placeholder-text-in-QLineEdits-with-action-icons.patch b/frameworks/qt5base/patches/116-fix-placement-of-placeholder-text-in-QLineEdits-with-action-icons.patch new file mode 100644 index 0000000..5edbc66 --- /dev/null +++ b/frameworks/qt5base/patches/116-fix-placement-of-placeholder-text-in-QLineEdits-with-action-icons.patch @@ -0,0 +1,144 @@ +Description: fix placement of placeholder text in QLineEdits with action icons + After dc794f7622bc00f7ca50fab65d6965695d6d2972, side widgets only got + space if they were not fading out, but the logic was not correctly + accounting for side widgets that never fade, such as buttons added via + QLineEdit::addAction. + . + Fix this to give visible widgets space, unless they are fading out. That + was the intent of the original change. Rename the variable to make its + purpose clearer, and reset it at the end of the fade-out animation. + . + Add a much-needed test that relies on private APIs to verify that the + effective margins are calculated correctly. +Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=0e6b31019f01c72e +Last-Update: 2021-08-10 + +--- a/src/widgets/widgets/qlineedit_p.cpp ++++ b/src/widgets/widgets/qlineedit_p.cpp +@@ -407,8 +407,9 @@ void QLineEditIconButton::setHideWithTex + + void QLineEditIconButton::onAnimationFinished() + { +- if (shouldHideWithText() && isVisible() && !m_wasHidden) { ++ if (shouldHideWithText() && isVisible() && m_fadingOut) { + hide(); ++ m_fadingOut = false; + + // Invalidate previous geometry to take into account new size of side widgets + if (auto le = lineEditPrivate()) +@@ -418,7 +419,7 @@ void QLineEditIconButton::onAnimationFin + + void QLineEditIconButton::animateShow(bool visible) + { +- m_wasHidden = visible; ++ m_fadingOut = !visible; + + if (shouldHideWithText() && !isVisible()) { + show(); +--- a/src/widgets/widgets/qlineedit_p.h ++++ b/src/widgets/widgets/qlineedit_p.h +@@ -95,8 +95,11 @@ public: + + bool shouldHideWithText() const; + void setHideWithText(bool hide); +- // m_wasHidden is true unless the button is fading out +- bool needsSpace() const { return m_wasHidden; } ++ bool needsSpace() const { ++ if (m_fadingOut) ++ return false; ++ return isVisibleTo(parentWidget()); ++ } + #endif + + protected: +@@ -120,7 +123,7 @@ private: + + #if QT_CONFIG(animation) + bool m_hideWithText = false; +- bool m_wasHidden = false; ++ bool m_fadingOut = false; + #endif + + }; +--- a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp ++++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp +@@ -292,6 +292,7 @@ private slots: + void clearButtonVisibleAfterSettingText_QTBUG_45518(); + void sideWidgets(); + void sideWidgetsActionEvents(); ++ void sideWidgetsEffectiveMargins(); + + void shouldShowPlaceholderText_data(); + void shouldShowPlaceholderText(); +@@ -4646,6 +4647,71 @@ void tst_QLineEdit::sideWidgetsActionEve + QCOMPARE(toolButton2->x(), toolButton1X); + } + ++/*! ++ Verify that side widgets are positioned correctly and result in ++ correct effective text margins. ++*/ ++void tst_QLineEdit::sideWidgetsEffectiveMargins() ++{ ++#ifndef QT_BUILD_INTERNAL ++ QSKIP("This test requires a developer build."); ++#else ++ QLineEdit edit; ++ edit.setPlaceholderText("placeholder"); ++ edit.setClearButtonEnabled(true); ++ edit.show(); ++ QLineEditPrivate *priv = QLineEditPrivate::get(&edit); ++ const auto sideWidgetParameters = priv->sideWidgetParameters(); ++ const int sideWidgetWidth = sideWidgetParameters.widgetWidth + sideWidgetParameters.margin; ++ QVERIFY(QTest::qWaitForWindowExposed(&edit)); ++ ++ QCOMPARE(priv->effectiveTextMargins().left(), 0); ++ QCOMPARE(priv->effectiveTextMargins().right(), 0); ++ ++ edit.setText("Left to right"); // clear button fades in on the right ++ QCOMPARE(priv->effectiveTextMargins().left(), 0); ++ QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth); ++ edit.clear(); ++ QCOMPARE(priv->effectiveTextMargins().left(), 0); ++ QCOMPARE(priv->effectiveTextMargins().right(), 0); ++ ++ edit.setLayoutDirection(Qt::RightToLeft); ++ edit.setText("ئۇيغۇر تىلى"); // clear button fades in on the left ++ QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth); ++ QCOMPARE(priv->effectiveTextMargins().right(), 0); ++ edit.clear(); ++ QCOMPARE(priv->effectiveTextMargins().left(), 0); ++ QCOMPARE(priv->effectiveTextMargins().right(), 0); ++ ++ edit.setLayoutDirection(Qt::LeftToRight); ++ ++ const QIcon leftIcon = edit.style()->standardIcon(QStyle::SP_FileIcon); ++ const QIcon rightIcon = edit.style()->standardIcon(QStyle::SP_DirIcon); ++ edit.addAction(leftIcon, QLineEdit::ActionPosition::LeadingPosition); ++ QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth); ++ QCOMPARE(priv->effectiveTextMargins().right(), 0); ++ ++ edit.addAction(rightIcon, QLineEdit::ActionPosition::TrailingPosition); ++ QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth); ++ QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth); ++ ++ edit.setText("Left to right"); // clear button on the right ++ QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth); ++ QCOMPARE(priv->effectiveTextMargins().right(), 2 * sideWidgetWidth); ++ edit.clear(); ++ QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth); ++ QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth); ++ ++ edit.setLayoutDirection(Qt::RightToLeft); ++ edit.setText("ئۇيغۇر تىلى"); // clear button fades in on the left ++ QCOMPARE(priv->effectiveTextMargins().left(), 2 * sideWidgetWidth); ++ QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth); ++ edit.clear(); ++ QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth); ++ QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth); ++#endif ++} ++ + Q_DECLARE_METATYPE(Qt::AlignmentFlag) + void tst_QLineEdit::shouldShowPlaceholderText_data() + { diff --git a/frameworks/qt5base/patches/120-gnukfreebsd.patch b/frameworks/qt5base/patches/120-gnukfreebsd.patch new file mode 100644 index 0000000..079c02f --- /dev/null +++ b/frameworks/qt5base/patches/120-gnukfreebsd.patch @@ -0,0 +1,168 @@ +Author: Pino Toscano +Description: Initial GNU/kFreeBSD support + - add a gnukfreebsd-g++ qmake mkspec, mostly copied from the hurd-g++ one + - properly use LD_LIBRARY_PATH on GNU/* systems +Last-Update: 2015-06-03 +Forwarded: no + +--- + mkspecs/features/qt_functions.prf | 2 + mkspecs/gnukfreebsd-g++/qmake.conf | 54 ++++++++++++++++++++ + mkspecs/gnukfreebsd-g++/qplatformdefs.h | 84 ++++++++++++++++++++++++++++++++ + 3 files changed, 140 insertions(+) + +--- /dev/null ++++ b/mkspecs/gnukfreebsd-g++/qmake.conf +@@ -0,0 +1,54 @@ ++# ++# qmake configuration for gnukfreebsd-g++ ++# ++ ++MAKEFILE_GENERATOR = UNIX ++QMAKE_PLATFORM += gnukfreebsd ++CONFIG += incremental ++QMAKE_INCREMENTAL_STYLE = sublib ++ ++QMAKE_CFLAGS_THREAD += -D_REENTRANT ++QMAKE_CXXFLAGS_THREAD += $$QMAKE_CFLAGS_THREAD ++QMAKE_LFLAGS_GCSECTIONS = -Wl,--gc-sections ++ ++QMAKE_INCDIR = ++QMAKE_LIBDIR = ++QMAKE_INCDIR_X11 = ++QMAKE_LIBDIR_X11 = ++QMAKE_INCDIR_OPENGL = ++QMAKE_LIBDIR_OPENGL = ++QMAKE_INCDIR_OPENGL_ES2 = $$QMAKE_INCDIR_OPENGL ++QMAKE_LIBDIR_OPENGL_ES2 = $$QMAKE_LIBDIR_OPENGL ++QMAKE_INCDIR_EGL = ++QMAKE_LIBDIR_EGL = ++QMAKE_INCDIR_OPENVG = ++QMAKE_LIBDIR_OPENVG = ++ ++QMAKE_LIBS = ++QMAKE_LIBS_DYNLOAD = -ldl ++QMAKE_LIBS_X11 = -lXext -lX11 -lm ++QMAKE_LIBS_NIS = -lnsl ++QMAKE_LIBS_EGL = -lEGL ++QMAKE_LIBS_OPENGL = -lGL ++QMAKE_LIBS_OPENGL_ES2 = -lGLESv2 ++QMAKE_LIBS_OPENVG = -lOpenVG ++QMAKE_LIBS_THREAD = -lpthread ++ ++QMAKE_CFLAGS_XCB = ++QMAKE_LIBS_XCB = ++QMAKE_DEFINES_XCB = ++ ++QMAKE_AR = ar cqs ++QMAKE_OBJCOPY = objcopy ++QMAKE_NM = nm -P ++QMAKE_RANLIB = ++ ++QMAKE_STRIP = strip ++QMAKE_STRIPFLAGS_LIB += --strip-unneeded ++QMAKE_INSTALL_FILE = install -m 644 -p ++QMAKE_INSTALL_PROGRAM = install -m 755 -p ++ ++include(../common/unix.conf) ++include(../common/gcc-base-unix.conf) ++include(../common/g++-unix.conf) ++load(qt_config) +--- /dev/null ++++ b/mkspecs/gnukfreebsd-g++/qplatformdefs.h +@@ -0,0 +1,84 @@ ++/**************************************************************************** ++** ++** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ++** Contact: http://www.qt-project.org/legal ++** ++** This file is part of the qmake spec of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:LGPL21$ ++** Commercial License Usage ++** Licensees holding valid commercial Qt licenses may use this file in ++** accordance with the commercial license agreement provided with the ++** Software or, alternatively, in accordance with the terms contained in ++** a written agreement between you and Digia. For licensing terms and ++** conditions see http://qt.digia.com/licensing. For further information ++** use the contact form at http://qt.digia.com/contact-us. ++** ++** GNU Lesser General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU Lesser ++** General Public License version 2.1 or version 3 as published by the Free ++** Software Foundation and appearing in the file LICENSE.LGPLv21 and ++** LICENSE.LGPLv3 included in the packaging of this file. Please review the ++** following information to ensure the GNU Lesser General Public License ++** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Digia gives you certain additional ++** rights. These rights are described in the Digia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++#ifndef QPLATFORMDEFS_H ++#define QPLATFORMDEFS_H ++ ++// Get Qt defines/settings ++ ++#include "qglobal.h" ++ ++// Set any POSIX/XOPEN defines at the top of this file to turn on specific APIs ++ ++// 1) need to reset default environment if _BSD_SOURCE is defined ++// 2) need to specify POSIX thread interfaces explicitly in glibc 2.0 ++// 3) it seems older glibc need this to include the X/Open stuff ++#ifndef _GNU_SOURCE ++# define _GNU_SOURCE ++#endif ++ ++#include ++ ++ ++// We are hot - unistd.h should have turned on the specific APIs we requested ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifndef QT_NO_IPV6IFNAME ++#include ++#endif ++ ++#include "../common/posix/qplatformdefs.h" ++ ++#if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500) ++#define QT_SNPRINTF ::snprintf ++#define QT_VSNPRINTF ::vsnprintf ++#endif ++ ++#endif // QPLATFORMDEFS_H +--- a/mkspecs/features/qt_functions.prf ++++ b/mkspecs/features/qt_functions.prf +@@ -215,6 +215,8 @@ defineTest(qtAddTargetEnv) { + deppath.name = PATH + } else:contains(QMAKE_HOST.os, Linux|FreeBSD|OpenBSD|NetBSD|DragonFly|SunOS|HP-UX|QNX|GNU) { + deppath.name = LD_LIBRARY_PATH ++ } else:contains(QMAKE_HOST.os, ^GNU/.*) { ++ deppath.name = LD_LIBRARY_PATH + } else:contains(QMAKE_HOST.os, Haiku) { + deppath.name = LIBRARY_PATH + } else:equals(QMAKE_HOST.os, Darwin) { diff --git a/frameworks/qt5base/patches/121-no_htmlinfo_example.patch b/frameworks/qt5base/patches/121-no_htmlinfo_example.patch new file mode 100644 index 0000000..8632c4a --- /dev/null +++ b/frameworks/qt5base/patches/121-no_htmlinfo_example.patch @@ -0,0 +1,15 @@ +Description: disable htmlinfo example which contains non-free files +Author: Dmitry Shachnev +Forwarded: not-needed +Last-Update: 2014-12-17 + +--- a/examples/xml/xml.pro ++++ b/examples/xml/xml.pro +@@ -1,6 +1,5 @@ + TEMPLATE = subdirs +-SUBDIRS = htmlinfo \ +- xmlstreamlint ++SUBDIRS = xmlstreamlint + + qtHaveModule(widgets) { + SUBDIRS += dombookmarks \ diff --git a/frameworks/qt5base/patches/122-remove_privacy_breaches.patch b/frameworks/qt5base/patches/122-remove_privacy_breaches.patch new file mode 100644 index 0000000..e911149 --- /dev/null +++ b/frameworks/qt5base/patches/122-remove_privacy_breaches.patch @@ -0,0 +1,26 @@ +Description: remove non-used privacy-breach code + This code makes Lintian unhappy. But we are really not using it, it only + gets inserted when building the online doc. + Anyways the best way to calm down Lintian is to simply remove it. +Author: Lisandro Damián Nicanor Pérez Meyer +Forwarded: not-needed +Last-Update: 2015-02-18 + +--- + doc/global/template/scripts/main.js | 5 ----- + 1 file changed, 5 deletions(-) + +--- a/doc/global/template/scripts/main.js ++++ b/doc/global/template/scripts/main.js +@@ -94,11 +94,6 @@ $(document).ready(function($) { + }); + + $( window ).load(function() { +- load_sdk('script', 'facebook-jssdk','//connect.facebook.net/en_US/sdk.js#xfbml=1&appId=207346529386114&version=v2.0'); +- load_sdk('script', 'twitter-wjs', '//platform.twitter.com/widgets.js'); +- $.getScript("//www.google.com/jsapi", function(){ +- google.load("feeds", "1", {"callback": oneQt.liveFeeds}); +- }); + }); + + var oneQt = { diff --git a/frameworks/qt5base/patches/123-link_fbclient.patch b/frameworks/qt5base/patches/123-link_fbclient.patch new file mode 100644 index 0000000..e2fed42 --- /dev/null +++ b/frameworks/qt5base/patches/123-link_fbclient.patch @@ -0,0 +1,17 @@ +Description: build ibase sql plugin against firebird +Author: Fathi Boudra +Author: Dmitry Shachnev +Forwarded: no +Last-Update: 2017-06-30 + +--- a/src/plugins/sqldrivers/configure.json ++++ b/src/plugins/sqldrivers/configure.json +@@ -52,7 +52,7 @@ + "headers": "ibase.h", + "sources": [ + { "libs": "-lgds32_ms", "condition": "config.win32" }, +- { "libs": "-lgds", "condition": "!config.win32" } ++ { "libs": "-lfbclient", "condition": "!config.win32" } + ] + }, + "mysql": { diff --git a/frameworks/qt5base/patches/124-gnukfreebsd_linker_warnings.patch b/frameworks/qt5base/patches/124-gnukfreebsd_linker_warnings.patch new file mode 100644 index 0000000..9e30c4c --- /dev/null +++ b/frameworks/qt5base/patches/124-gnukfreebsd_linker_warnings.patch @@ -0,0 +1,40 @@ +Description: catch linker warnings in some config tests + Without this, qmake wrongly thinks that the tests succeed, for example: + . + ./config.tests/unix/futimens/futimens.cpp:44: warning: futimens is not implemented and will always fail + test config.corelib.tests.futimens succeeded +Author: Dmitry Shachnev +Forwarded: https://codereview.qt-project.org/163214 (rejected) +Bug: https://bugs.debian.org/827935 +Last-Update: 2019-03-02 + +--- + src/corelib/configure.json | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/src/corelib/configure.json ++++ b/src/corelib/configure.json +@@ -331,6 +331,7 @@ + "label": "O_CLOEXEC", + "type": "compile", + "test": { ++ "qmake": "QMAKE_LFLAGS += -Wl,--fatal-warnings", + "head": "#define _GNU_SOURCE 1", + "include": [ "sys/types.h", "sys/socket.h", "fcntl.h", "unistd.h" ], + "main": [ +@@ -386,6 +387,7 @@ + "include": "sys/stat.h", + "main": "futimens(-1, 0);", + "qmake": [ ++ "QMAKE_LFLAGS += -Wl,--fatal-warnings", + "# Block futimens() on Apple platforms unless it's available on ALL", + "# deployment targets. This simplifies the logic at the call site", + "# dramatically, as it isn't strictly needed compared to futimes().", +@@ -414,6 +416,7 @@ + "label": "getentropy()", + "type": "compile", + "test": { ++ "qmake": "QMAKE_LFLAGS += -Wl,--fatal-warnings", + "include": "unistd.h", + "main": [ + "char buf[32];", diff --git a/frameworks/qt5base/patches/125-armv4.patch b/frameworks/qt5base/patches/125-armv4.patch new file mode 100644 index 0000000..531a29b --- /dev/null +++ b/frameworks/qt5base/patches/125-armv4.patch @@ -0,0 +1,26 @@ +Description: support ARMv4 architecture, needed for armel builds +Author: Dmitry Shachnev +Forwarded: no +Last-Update: 2016-07-01 + +--- a/src/corelib/global/qprocessordetection.h ++++ b/src/corelib/global/qprocessordetection.h +@@ -132,6 +132,8 @@ + # elif defined(__ARM_ARCH_5TEJ__) \ + || defined(__ARM_ARCH_5TE__) + # define Q_PROCESSOR_ARM 5 ++# elif defined(__ARM_ARCH_4T__) ++# define Q_PROCESSOR_ARM 4 + # else + # define Q_PROCESSOR_ARM 0 + # endif +@@ -146,6 +148,9 @@ + # endif + # if Q_PROCESSOR_ARM >= 5 + # define Q_PROCESSOR_ARM_V5 ++# endif ++# if Q_PROCESSOR_ARM >= 4 ++# define Q_PROCESSOR_ARM_V4 + # else + # error "ARM architecture too old" + # endif diff --git a/frameworks/qt5base/patches/126-nonlinux_utime.patch b/frameworks/qt5base/patches/126-nonlinux_utime.patch new file mode 100644 index 0000000..ae67a47 --- /dev/null +++ b/frameworks/qt5base/patches/126-nonlinux_utime.patch @@ -0,0 +1,33 @@ +Description: guard UTIME_NOW/UTIME_OMIT usages +Author: Dmitry Shachnev +Author: Pino Toscano +Forwarded: no +Last-Update: 2018-02-22 + +--- + qmake/library/ioutils.cpp | 2 +- + src/corelib/io/qfilesystemengine_unix.cpp | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/qmake/library/ioutils.cpp ++++ b/qmake/library/ioutils.cpp +@@ -228,7 +228,7 @@ bool IoUtils::touchFile(const QString &t + *errorString = fL1S("Cannot stat() reference file %1: %2.").arg(referenceFileName, fL1S(strerror(errno))); + return false; + } +-# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ++# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L && defined(UTIME_NOW) + const struct timespec times[2] = { { 0, UTIME_NOW }, st.st_mtim }; + const bool utimeError = utimensat(AT_FDCWD, targetFileName.toLocal8Bit().constData(), times, 0) < 0; + # else +--- a/src/corelib/io/qfilesystemengine_unix.cpp ++++ b/src/corelib/io/qfilesystemengine_unix.cpp +@@ -1595,7 +1595,7 @@ bool QFileSystemEngine::setFileTime(int + return false; + } + +-#if QT_CONFIG(futimens) ++#if QT_CONFIG(futimens) && defined(UTIME_OMIT) + struct timespec ts[2]; + + ts[0].tv_sec = ts[1].tv_sec = 0; diff --git a/frameworks/qt5base/patches/127-qdoc_default_incdirs.patch b/frameworks/qt5base/patches/127-qdoc_default_incdirs.patch new file mode 100644 index 0000000..4c559a3 --- /dev/null +++ b/frameworks/qt5base/patches/127-qdoc_default_incdirs.patch @@ -0,0 +1,23 @@ +Description: pass default include directories to qdoc +Author: Martin Smith +Bug: https://bugs.debian.org/908328 +Forwarded: no +Last-Update: 2020-01-28 + +--- + mkspecs/features/qt_docs.prf | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/mkspecs/features/qt_docs.prf ++++ b/mkspecs/features/qt_docs.prf +@@ -98,6 +98,10 @@ doc_command = $$QDOC $$QMAKE_DOCS + prepare_docs { + prepare_docs.commands += $$doc_command -prepare $$PREP_DOC_INDEXES -no-link-errors $$QDOC_INCLUDE_PATHS + generate_docs.commands += $$doc_command -generate $$DOC_INDEXES $$QDOC_INCLUDE_PATHS ++ for (incdir, QMAKE_DEFAULT_INCDIRS) { ++ prepare_docs.commands += -I$$shell_quote($$incdir) ++ generate_docs.commands += -I$$shell_quote($$incdir) ++ } + prepare_docs.depends += qtattributionsscanner + } else { + html_docs.commands += $$doc_command $$DOC_INDEXES $(QDOC_INCLUDE_PATHS) diff --git a/frameworks/qt5base/patches/128-path_max.patch b/frameworks/qt5base/patches/128-path_max.patch new file mode 100644 index 0000000..b9014fa --- /dev/null +++ b/frameworks/qt5base/patches/128-path_max.patch @@ -0,0 +1,21 @@ +Author: Pino Toscano +Description: Avoid unconditional PATH_MAX usage + Use a "safe" size in case PATH_MAX is not defined; in the end, this should not + be used, as a allocating realpath() will be used instead. +Forwarded: no +Last-Update: 2020-04-19 + +--- a/src/corelib/io/qfilesystemengine_unix.cpp ++++ b/src/corelib/io/qfilesystemengine_unix.cpp +@@ -689,7 +689,11 @@ QFileSystemEntry QFileSystemEngine::cano + Q_UNUSED(data); + return QFileSystemEntry(slowCanonicalized(absoluteName(entry).filePath())); + #else ++#ifdef PATH_MAX + char stack_result[PATH_MAX+1]; ++#else ++ char stack_result[4096+1]; ++#endif + char *resolved_name = nullptr; + # if defined(Q_OS_DARWIN) || defined(Q_OS_ANDROID) + // On some Android and macOS versions, realpath() will return a path even if diff --git a/frameworks/qt5base/patches/129-qstorageinfo_linux.patch b/frameworks/qt5base/patches/129-qstorageinfo_linux.patch new file mode 100644 index 0000000..b1da1fc --- /dev/null +++ b/frameworks/qt5base/patches/129-qstorageinfo_linux.patch @@ -0,0 +1,28 @@ +Author: Pino Toscano +Description: Limit Linux-only code with Q_OS_LINUX + The QStorageInfo/QStorageIterator implementation used for Linux is used also + on Hurd, as it uses an interface provided by GNU libc. + QStorageIterator::device() tries to use PATH_MAX (unavailable on the Hurd) + to lookup a /dev/block/ path, which exists on Linux only; hence, perform that + check within a Q_OS_LINUX block. +Forwarded: no +Last-Update: 2020-04-19 + +--- a/src/corelib/io/qstorageinfo_unix.cpp ++++ b/src/corelib/io/qstorageinfo_unix.cpp +@@ -566,6 +566,7 @@ inline QByteArray QStorageIterator::file + + inline QByteArray QStorageIterator::device() const + { ++#ifdef Q_OS_LINUX + // check that the device exists + if (mnt.mnt_fsname[0] == '/' && access(mnt.mnt_fsname, F_OK) != 0) { + // It doesn't, so let's try to resolve the dev_t from /dev/block. +@@ -581,6 +582,7 @@ inline QByteArray QStorageIterator::devi + return dev; + } + } ++#endif + return QByteArray(mnt.mnt_fsname); + } + diff --git a/frameworks/qt5base/patches/130-cross_build_mysql.patch b/frameworks/qt5base/patches/130-cross_build_mysql.patch new file mode 100644 index 0000000..9d5ce09 --- /dev/null +++ b/frameworks/qt5base/patches/130-cross_build_mysql.patch @@ -0,0 +1,20 @@ +Description: call pkgconfig in order to be able to cross build qtbase with MySql. + Qt's build system calls mysql_config... which won't work in a cross build + environment like Debian's, as it will throw an exec format error. + . + In order to solve this call pkgconfig and use mysqlclient.pc. +Author: Helmut Grohne +Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=971604 +Forwarded: not-needed +Reviewed-by: Lisandro Damián Nicanor Pérez Meyer + +--- qtbase-opensource-src-5.14.2+dfsg.orig/src/plugins/sqldrivers/configure.json ++++ qtbase-opensource-src-5.14.2+dfsg/src/plugins/sqldrivers/configure.json +@@ -67,6 +67,7 @@ + }, + "headers": "mysql.h", + "sources": [ ++ { "type": "pkgConfig", "args": "mysqlclient" }, + { "type": "mysqlConfig", "query": "--libs_r", "cleanlibs": true }, + { "type": "mysqlConfig", "query": "--libs", "cleanlibs": true }, + { "type": "mysqlConfig", "query": "--libs_r", "cleanlibs": false }, diff --git a/frameworks/qt5base/patches/131-cast_types_for_egl_x11_test.patch b/frameworks/qt5base/patches/131-cast_types_for_egl_x11_test.patch new file mode 100644 index 0000000..547ef00 --- /dev/null +++ b/frameworks/qt5base/patches/131-cast_types_for_egl_x11_test.patch @@ -0,0 +1,19 @@ +Description: properly cast types for libglvnd 1.3.4 +Origin: https://src.fedoraproject.org/rpms/qt5-qtbase/blob/rawhide/f/qtbase-everywhere-src-5.15.2-libglvnd.patch +Author: Rex Dieter + +diff -up qtbase-everywhere-src-5.15.2/src/gui/configure.json.libglvnd qtbase-everywhere-src-5.15.2/src/gui/configure.json +--- qtbase-everywhere-src-5.15.2/src/gui/configure.json.libglvnd 2020-10-27 03:02:11.000000000 -0500 ++++ qtbase-everywhere-src-5.15.2/src/gui/configure.json 2021-09-10 10:05:53.610312223 -0500 +@@ -847,9 +847,9 @@ + ], + "include": [ "EGL/egl.h", "X11/Xlib.h" ], + "main": [ +- "Display *dpy = EGL_DEFAULT_DISPLAY;", ++ "Display *dpy = reinterpret_cast(EGL_DEFAULT_DISPLAY);", + "EGLNativeDisplayType egldpy = XOpenDisplay(\"\");", +- "dpy = egldpy;", ++ "dpy = reinterpret_cast(egldpy);", + "EGLNativeWindowType w = XCreateWindow(dpy, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);", + "XDestroyWindow(dpy, w);", + "XCloseDisplay(dpy);"