From 851d69eebc717858f912081b24bd2223ed641aeb Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 31 Jan 2022 11:00:19 -0800 Subject: QProcess/Unix: ensure we don't accidentally execute something from CWD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 [ChangeLog][Important Behavior Changes] When passed a simple program name with no slashes, QProcess on Unix systems will now only search the current directory if "." is one of the entries in the PATH environment variable. This bug fix restores the behavior QProcess had before Qt 5.9. If launching an executable in the directory set by setWorkingDirectory() or inherited from the parent is intended, pass a program name starting with "./". For more information and best practices about finding an executable, see QProcess' documentation. Change-Id: I54f205f6b7314351b078fffd16cf7013c97ee9fb Reviewed-by: Qt CI Bot Reviewed-by: Mårten Nordheim Reviewed-by: Thiago Macieira (cherry picked from commit 29fceed2ffb41954a63001414bd042611f2d4980) Reviewed-by: Jörg Bornemann --- tests/auto/corelib/global/qlogging/tst_qlogging.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'tests/auto/corelib/global') diff --git a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp index 3af637d13a..0f27901f94 100644 --- a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp +++ b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp @@ -34,6 +34,8 @@ #endif #include +#include + class tst_qmessagehandler : public QObject { Q_OBJECT @@ -819,7 +821,17 @@ void tst_qmessagehandler::qMessagePattern() QFETCH(QList, expected); QProcess process; -#ifndef Q_OS_ANDROID + + // Add the executable's directory to path so that we can find the test helper next to it + // in a cross-platform way. We must do this because the CWD is not pointing to this directory + // in debug-and-release builds. + QByteArray path = qgetenv("PATH"); + qputenv("PATH", + path + QDir::listSeparator().toLatin1() + + QCoreApplication::applicationDirPath().toLocal8Bit()); + auto restore = qScopeGuard([&] { qputenv("PATH", path); }); + +#if !defined(Q_OS_ANDROID) const QString appExe(QLatin1String("helper")); #else const QString appExe(QCoreApplication::applicationDirPath() + QLatin1String("/libhelper.so")); @@ -869,8 +881,12 @@ void tst_qmessagehandler::setMessagePattern() // QProcess process; -#ifndef Q_OS_ANDROID +#ifdef Q_OS_WIN + // On Windows the CWD is not the same directory as the helper, so we cannot use "./" + // Instead we rely on CreateProcess to find the executable. const QString appExe(QLatin1String("helper")); +#elif !defined(Q_OS_ANDROID) + const QString appExe(QLatin1String("./helper")); #else const QString appExe(QCoreApplication::applicationDirPath() + QLatin1String("/libhelper.so")); #endif -- cgit v1.2.1 From e00397efe39fcb86bca6b6e86034889bef7ba309 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 25 Feb 2022 18:16:04 +0100 Subject: Backport recent QFlags tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a backport of the tst_qflags parts of - 6f50e54138f9a2aa9ab6d84add449f197d545de3 (QFlags: fix missing bitwise xor operators in QT_TYPESAFE_FLAGS builds) - 53890b5d3cd771d66d6b73940eb38e3c3fc6d60f (qtestmouse.h: compile with QT_TYPESAFE_FLAGS) These changes were originally only picked to 6.3 because it was thought only 6.3 was failing the tests. In order to check that this is indeed the case, and to help future cherry-picking, backport the tst_qflags additions to 6.2 and 5.15. Change-Id: Iecfa11a8a83388c60f659238a28a26142b579380 Reviewed-by: Giuseppe D'Angelo (cherry picked from commit 4feaf095f44861fb93694483ac209b14974bf037) Reviewed-by: Mårten Nordheim Reviewed-by: Qt CI Bot --- tests/auto/corelib/global/qflags/tst_qflags.cpp | 69 +++++++++++++++++++++++++ 1 file changed, 69 insertions(+) (limited to 'tests/auto/corelib/global') diff --git a/tests/auto/corelib/global/qflags/tst_qflags.cpp b/tests/auto/corelib/global/qflags/tst_qflags.cpp index c679fbd8e3..fdbd95c64c 100644 --- a/tests/auto/corelib/global/qflags/tst_qflags.cpp +++ b/tests/auto/corelib/global/qflags/tst_qflags.cpp @@ -31,6 +31,8 @@ class tst_QFlags: public QObject { Q_OBJECT private slots: + void boolCasts() const; + void operators() const; void testFlag() const; void testFlagZeroFlag() const; void testFlagMultiBits() const; @@ -42,6 +44,73 @@ private slots: void adl(); }; +void tst_QFlags::boolCasts() const +{ + // This tests that the operator overloading is sufficient so that common + // idioms involving flags -> bool casts work as expected: + + const Qt::Alignment nonNull = Qt::AlignCenter; + const Qt::Alignment null = {}; + + // basic premiss: + QVERIFY(bool(nonNull)); + QVERIFY(!bool(null)); + + // The rest is just checking that stuff compiles: + + // QVERIFY should compile: + QVERIFY(nonNull); + QVERIFY(!null); + + // ifs should compile: + if (null) QFAIL("Can't contextually convert QFlags to bool!"); + if (!nonNull) QFAIL("Missing operator! on QFlags (shouldn't be necessary)."); + + // ternary should compile: + QVERIFY(nonNull ? true : false); + QVERIFY(!null ? true : false); + + // logical operators should compile: + QVERIFY(nonNull && true); + QVERIFY(nonNull || false); + QVERIFY(!null && true); + QVERIFY(!null || false); + + // ... in both directions: + QVERIFY(true && nonNull); + QVERIFY(false || nonNull); + QVERIFY(true && !null); + QVERIFY(false || !null); + + // ... and mixed: + QVERIFY(null || nonNull); + QVERIFY(!(null && nonNull)); +} + +void tst_QFlags::operators() const +{ +#define CHECK(op, LHS, RHS, RES) \ + do { \ + using LFlags = QFlags; \ + using RFlags = QFlags; \ + QCOMPARE((LHS op RHS), (RES)); \ + QCOMPARE((LFlags(LHS) op RHS), (RES)); \ + QCOMPARE((LHS op RFlags(RHS)), (RES)); \ + QCOMPARE((LFlags(LHS) op RFlags(RHS)), (RES)); \ + QCOMPARE((LFlags(LHS) op ## = RHS), (RES)); \ + QCOMPARE((LFlags(LHS) op ## = RFlags(RHS)), (RES)); \ + } while (false) + + CHECK(|, Qt::AlignHCenter, Qt::AlignVCenter, Qt::AlignCenter); + CHECK(|, Qt::AlignHCenter, Qt::AlignHCenter, Qt::AlignHCenter); + CHECK(&, Qt::AlignHCenter, Qt::AlignVCenter, Qt::Alignment()); + CHECK(&, Qt::AlignHCenter, Qt::AlignHCenter, Qt::AlignHCenter); + CHECK(^, Qt::AlignHCenter, Qt::AlignVCenter, Qt::AlignCenter); + CHECK(^, Qt::AlignHCenter, Qt::AlignHCenter, Qt::Alignment()); + +#undef CHECK +} + void tst_QFlags::testFlag() const { Qt::MouseButtons btn = Qt::LeftButton | Qt::RightButton; -- cgit v1.2.1