From f79653523310bb8ad7b8fc867488fc69c673301a Mon Sep 17 00:00:00 2001 From: ComixHe Date: Thu, 19 Oct 2023 14:18:44 +0800 Subject: [PATCH] fix: unescape exec before pass this arg to wordexp Signed-off-by: ComixHe --- src/dbus/applicationservice.cpp | 28 ++++++++++++++++---- src/dbus/applicationservice.h | 38 +++++++++++++------------- src/desktopentry.cpp | 10 ++++--- src/desktopentry.h | 2 +- tests/ut_escapeexec.cpp | 47 +++++++++++++++++++++++++++++++++ 5 files changed, 98 insertions(+), 27 deletions(-) create mode 100644 tests/ut_escapeexec.cpp diff --git a/src/dbus/applicationservice.cpp b/src/dbus/applicationservice.cpp index cf1dcab..61201ff 100644 --- a/src/dbus/applicationservice.cpp +++ b/src/dbus/applicationservice.cpp @@ -9,6 +9,7 @@ #include "propertiesForwarder.h" #include "dbus/instanceadaptor.h" #include "launchoptions.h" +#include "desktopentry.h" #include #include #include @@ -197,7 +198,8 @@ QDBusObjectPath ApplicationService::Launch(const QString &action, const QStringL sendErrorReply(QDBusError::Failed, msg); return {}; } - execStr = toString(Actions.value()); + + execStr = Actions.value().toString(); if (execStr.isEmpty()) { QString msg{"maybe entry actions's format is invalid, abort launch."}; qWarning() << msg; @@ -733,13 +735,21 @@ void ApplicationService::resetEntry(DesktopEntry *newEntry) noexcept emit scaleFactorChanged(); } -LaunchTask ApplicationService::unescapeExec(const QString &str, const QStringList &fields) +QStringList ApplicationService::unescapeExecArgs(const QString &str) noexcept { - LaunchTask task; - auto deleter = [](wordexp_t *word) { wordfree(word); }; + auto unescapedStr = unescape(str, true); + if (unescapedStr.isEmpty()) { + qWarning() << "unescape Exec failed."; + return {}; + } + + auto deleter = [](wordexp_t *word) { + wordfree(word); + delete word; + }; std::unique_ptr words{new (std::nothrow) wordexp_t{0, nullptr, 0}, deleter}; - if (auto ret = wordexp(str.toLocal8Bit().constData(), words.get(), WRDE_SHOWERR); ret != 0) { + if (auto ret = wordexp(unescapedStr.toLocal8Bit(), words.get(), WRDE_SHOWERR); ret != 0) { if (ret != 0) { QString errMessage; switch (ret) { @@ -771,6 +781,14 @@ LaunchTask ApplicationService::unescapeExec(const QString &str, const QStringLis for (int i = 0; i < words->we_wordc; ++i) { execList.emplace_back(words->we_wordv[i]); } + + return execList; +} + +LaunchTask ApplicationService::unescapeExec(const QString &str, const QStringList &fields) noexcept +{ + LaunchTask task; + auto execList = unescapeExecArgs(str); task.LaunchBin = execList.first(); QRegularExpression re{"%[fFuUickdDnNvm]"}; diff --git a/src/dbus/applicationservice.h b/src/dbus/applicationservice.h index f8e1f7a..2f620b7 100644 --- a/src/dbus/applicationservice.h +++ b/src/dbus/applicationservice.h @@ -5,25 +5,25 @@ #ifndef APPLICATIONSERVICE_H #define APPLICATIONSERVICE_H -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "applicationmanager1service.h" #include "applicationmanagerstorage.h" #include "dbus/applicationmanager1service.h" #include "dbus/instanceservice.h" -#include "global.h" -#include "desktopentry.h" #include "dbus/jobmanager1service.h" -#include "applicationmanager1service.h" +#include "desktopentry.h" +#include "global.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include QString getDeepinWineScaleFactor(const QString &appId) noexcept; double getScaleFactor() noexcept; @@ -70,8 +70,8 @@ public: [[nodiscard]] bool terminal() const noexcept; // FIXME: - // This property should implement with fuse guarded $XDG_CONFIG_HOME/autostart/. - // Current implementation has some problems, + // This property should implement with fuse guarded + // $XDG_CONFIG_HOME/autostart/. Current implementation has some problems, Q_PROPERTY(bool AutoStart READ isAutoStart WRITE setAutoStart NOTIFY autostartChanged) [[nodiscard]] bool isAutoStart() const noexcept; void setAutoStart(bool autostart) noexcept; @@ -119,6 +119,9 @@ public: void resetEntry(DesktopEntry *newEntry) noexcept; void detachAllInstance() noexcept; + [[nodiscard]] LaunchTask unescapeExec(const QString &str, const QStringList &fields) noexcept; + [[nodiscard]] static QStringList unescapeExecArgs(const QString &str) noexcept; + private Q_SLOTS: void onGlobalScaleFactorChanged() noexcept; @@ -165,7 +168,6 @@ private: DesktopFile m_desktopSource; QSharedPointer m_entry{nullptr}; QMap> m_Instances; - [[nodiscard]] LaunchTask unescapeExec(const QString &str, const QStringList &fields); [[nodiscard]] QVariant findEntryValue(const QString &group, const QString &valueKey, EntryValueType type, diff --git a/src/desktopentry.cpp b/src/desktopentry.cpp index 4c41c29..95a6042 100644 --- a/src/desktopentry.cpp +++ b/src/desktopentry.cpp @@ -236,7 +236,7 @@ std::optional DesktopEntry::value(const QString &groupKey, return *it; } -QString unescape(const QString &str) noexcept +QString unescape(const QString &str, bool shellMode) noexcept { QString unescapedStr; for (qsizetype i = 0; i < str.size(); ++i) { @@ -270,10 +270,13 @@ QString unescape(const QString &str) noexcept unescapedStr.append(';'); ++i; break; - case 's': + case 's': { + if (shellMode) { // for wordexp + unescapedStr.append('\\'); + } unescapedStr.append(' '); ++i; - break; + } break; } } @@ -296,6 +299,7 @@ QString toString(const DesktopEntry::Value &value) noexcept } auto unescapedStr = unescape(str); + if (hasNonAsciiAndControlCharacters(unescapedStr)) { return {}; } diff --git a/src/desktopentry.h b/src/desktopentry.h index 74f5155..c445cf7 100644 --- a/src/desktopentry.h +++ b/src/desktopentry.h @@ -137,7 +137,7 @@ bool operator==(const DesktopFile &lhs, const DesktopFile &rhs); bool operator!=(const DesktopFile &lhs, const DesktopFile &rhs); -QString unescape(const QString &str) noexcept; +QString unescape(const QString &str, bool shellMode = false) noexcept; QString toLocaleString(const QStringMap &localeMap, const QLocale &locale) noexcept; diff --git a/tests/ut_escapeexec.cpp b/tests/ut_escapeexec.cpp new file mode 100644 index 0000000..205e013 --- /dev/null +++ b/tests/ut_escapeexec.cpp @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "dbus/applicationservice.h" +#include +#include + +TEST(UnescapeExec, blankSpace) +{ + QList>> testCases{ + { + R"(/usr/bin/hello\sworld --arg1=val1 -h --str="rrr ggg bbb")", + { + "/usr/bin/hello world", + "--arg1=val1", + "-h", + "--str=rrr ggg bbb", + }, + }, + { + R"("/usr/bin/hello world" a b -- "c d")", + { + "/usr/bin/hello world", + "a", + "b", + "--", + "c d", + }, + }, + { + R"("/usr/bin/hello\t\nworld" a b -- c d)", + { + "/usr/bin/hello\t\nworld", + "a", + "b", + "--", + "c", + "d", + }, + }, + }; + + for (auto &testCase : testCases) { + EXPECT_EQ(ApplicationService::unescapeExecArgs(testCase.first), testCase.second); + } +}