From 376cb01a163fa6bc5375a13421e5e527b5499893 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Sun, 19 Dec 2021 12:32:15 +0100 Subject: [PATCH] patterns: Disallow calling of dangerous functions by default Closes #330 --- .../source/content/pl_builtin_functions.cpp | 32 +++++++++---------- .../content/views/view_pattern_editor.cpp | 32 ++++++++++++++++--- plugins/builtin/source/lang/de_DE.cpp | 4 +++ plugins/builtin/source/lang/en_US.cpp | 4 +++ plugins/builtin/source/lang/it_IT.cpp | 4 +++ plugins/builtin/source/lang/zh_CN.cpp | 4 +++ .../include/hex/api/content_registry.hpp | 3 +- .../include/hex/pattern_language/ast_node.hpp | 20 +++++++++++- .../hex/pattern_language/evaluator.hpp | 28 ++++++++++++++++ .../hex/pattern_language/pattern_language.hpp | 4 +++ .../libimhex/source/api/content_registry.cpp | 4 +-- .../source/pattern_language/evaluator.cpp | 5 +++ .../pattern_language/pattern_language.cpp | 9 ++++++ 13 files changed, 128 insertions(+), 25 deletions(-) diff --git a/plugins/builtin/source/content/pl_builtin_functions.cpp b/plugins/builtin/source/content/pl_builtin_functions.cpp index 8c688fe5b..78b14f0bf 100644 --- a/plugins/builtin/source/content/pl_builtin_functions.cpp +++ b/plugins/builtin/source/content/pl_builtin_functions.cpp @@ -206,12 +206,12 @@ namespace hex::plugin::builtin { auto string = Token::literalToString(params[0], false); auto index = Token::literalToSigned(params[1]); -#if defined(OS_MACOS) - const auto signIndex = index >> (sizeof(index) * 8 - 1); - const auto absIndex = (index ^ signIndex) - signIndex; -#else - const auto absIndex = std::abs(index); -#endif + #if defined(OS_MACOS) + const auto signIndex = index >> (sizeof(index) * 8 - 1); + const auto absIndex = (index ^ signIndex) - signIndex; + #else + const auto absIndex = std::abs(index); + #endif if (absIndex > string.length()) LogConsole::abortEvaluation("character index out of range"); @@ -259,7 +259,7 @@ namespace hex::plugin::builtin { hex::Net net; return net.getString(url).get().body; - }); + }, true); } @@ -292,7 +292,7 @@ namespace hex::plugin::builtin { openFiles.emplace(std::pair{ fileCounter, std::move(file) }); return u128(fileCounter); - }); + }, true); /* close(file) */ ContentRegistry::PatternLanguageFunctions::add(nsStdFile, "close", 1, [](Evaluator *ctx, auto params) -> std::optional { @@ -304,7 +304,7 @@ namespace hex::plugin::builtin { openFiles.erase(file); return { }; - }); + }, true); /* read(file, size) */ ContentRegistry::PatternLanguageFunctions::add(nsStdFile, "read", 2, [](Evaluator *ctx, auto params) -> std::optional { @@ -315,7 +315,7 @@ namespace hex::plugin::builtin { LogConsole::abortEvaluation("failed to access invalid file"); return openFiles[file].readString(size); - }); + }, true); /* write(file, data) */ ContentRegistry::PatternLanguageFunctions::add(nsStdFile, "write", 2, [](Evaluator *ctx, auto params) -> std::optional { @@ -328,7 +328,7 @@ namespace hex::plugin::builtin { openFiles[file].write(data); return { }; - }); + }, true); /* seek(file, offset) */ ContentRegistry::PatternLanguageFunctions::add(nsStdFile, "seek", 2, [](Evaluator *ctx, auto params) -> std::optional { @@ -341,7 +341,7 @@ namespace hex::plugin::builtin { openFiles[file].seek(offset); return { }; - }); + }, true); /* size(file) */ ContentRegistry::PatternLanguageFunctions::add(nsStdFile, "size", 1, [](Evaluator *ctx, auto params) -> std::optional { @@ -351,7 +351,7 @@ namespace hex::plugin::builtin { LogConsole::abortEvaluation("failed to access invalid file"); return u128(openFiles[file].getSize()); - }); + }, true); /* resize(file, size) */ ContentRegistry::PatternLanguageFunctions::add(nsStdFile, "resize", 2, [](Evaluator *ctx, auto params) -> std::optional { @@ -364,7 +364,7 @@ namespace hex::plugin::builtin { openFiles[file].setSize(size); return { }; - }); + }, true); /* flush(file) */ ContentRegistry::PatternLanguageFunctions::add(nsStdFile, "flush", 1, [](Evaluator *ctx, auto params) -> std::optional { @@ -376,7 +376,7 @@ namespace hex::plugin::builtin { openFiles[file].flush(); return { }; - }); + }, true); /* remove(file) */ ContentRegistry::PatternLanguageFunctions::add(nsStdFile, "remove", 1, [](Evaluator *ctx, auto params) -> std::optional { @@ -388,7 +388,7 @@ namespace hex::plugin::builtin { openFiles[file].remove(); return { }; - }); + }, true); } } diff --git a/plugins/builtin/source/content/views/view_pattern_editor.cpp b/plugins/builtin/source/content/views/view_pattern_editor.cpp index 74247e148..4de10b77e 100644 --- a/plugins/builtin/source/content/views/view_pattern_editor.cpp +++ b/plugins/builtin/source/content/views/view_pattern_editor.cpp @@ -243,16 +243,16 @@ namespace hex::plugin::builtin { auto size = ImGui::GetContentRegionAvail(); size.y -= ImGui::GetTextLineHeightWithSpacing() * 2.5; - if (ImGui::BeginTabBar("settings")) { - if (ImGui::BeginTabItem("Console")) { + if (ImGui::BeginTabBar("##settings")) { + if (ImGui::BeginTabItem("hex.builtin.view.pattern_editor.console"_lang)) { this->drawConsole(size); ImGui::EndTabItem(); } - if (ImGui::BeginTabItem("Environment Variables")) { + if (ImGui::BeginTabItem("hex.builtin.view.pattern_editor.env_vars"_lang)) { this->drawEnvVars(size); ImGui::EndTabItem(); } - if (ImGui::BeginTabItem("Settings")) { + if (ImGui::BeginTabItem("hex.builtin.view.pattern_editor.settings"_lang)) { this->drawVariableSettings(size); ImGui::EndTabItem(); } @@ -309,6 +309,28 @@ namespace hex::plugin::builtin { } } + if (this->m_evaluatorRuntime->hasDangerousFunctionBeenCalled() && !ImGui::IsPopupOpen(View::toWindowName("hex.builtin.view.pattern_editor.dangerous_function.name").c_str())) { + ImGui::OpenPopup(View::toWindowName("hex.builtin.view.pattern_editor.dangerous_function.name").c_str()); + } + + if (ImGui::BeginPopupModal(View::toWindowName("hex.builtin.view.pattern_editor.dangerous_function.name").c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize)) { + ImGui::NewLine(); + ImGui::TextUnformatted("hex.builtin.view.pattern_editor.dangerous_function.desc"_lang); + ImGui::NewLine(); + + View::confirmButtons("hex.common.yes"_lang, "hex.common.no"_lang, + [this]{ + this->m_evaluatorRuntime->allowDangerousFunctions(true); + ImGui::CloseCurrentPopup(); + }, + [this]{ + this->m_evaluatorRuntime->allowDangerousFunctions(false); + ImGui::CloseCurrentPopup(); + }); + + ImGui::EndPopup(); + } + View::discardNavigationRequests(); } ImGui::End(); @@ -442,7 +464,7 @@ namespace hex::plugin::builtin { void ViewPatternEditor::drawVariableSettings(ImVec2 size) { if (ImGui::BeginChild("##settings", size, true, ImGuiWindowFlags_AlwaysVerticalScrollbar)) { - if (ImGui::BeginTable("##env_vars_table", 2, ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_BordersInnerH)) { + if (ImGui::BeginTable("##in_out_vars_table", 2, ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_BordersInnerH)) { ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch, 0.4F); ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch, 0.6F); diff --git a/plugins/builtin/source/lang/de_DE.cpp b/plugins/builtin/source/lang/de_DE.cpp index 0a20a218c..a8a5b7812 100644 --- a/plugins/builtin/source/lang/de_DE.cpp +++ b/plugins/builtin/source/lang/de_DE.cpp @@ -273,7 +273,11 @@ namespace hex::plugin::builtin { { "hex.builtin.view.pattern_editor.open_pattern", "Pattern öffnen" }, { "hex.builtin.view.pattern_editor.evaluating", "Evaluieren..." }, { "hex.builtin.view.pattern_editor.auto", "Auto evaluieren" }, + { "hex.builtin.view.pattern_editor.console", "Konsole" }, { "hex.builtin.view.pattern_editor.env_vars", "Umgebungsvariablen" }, + { "hex.builtin.view.pattern_editor.settings", "Einstellungen" }, + { "hex.builtin.view.pattern_editor.dangerous_function.name", "Gefährliche funktion erlauben?" }, + { "hex.builtin.view.pattern_editor.dangerous_function.desc", "Dieses Pattern hat versucht eine gefährliche Funktion aufzurufen.\nBist du sicher, dass du diesem Pattern vertraust?" }, { "hex.builtin.view.pattern_data.name", "Pattern Daten" }, { "hex.builtin.view.pattern_data.var_name", "Name" }, diff --git a/plugins/builtin/source/lang/en_US.cpp b/plugins/builtin/source/lang/en_US.cpp index ff9da8764..9dbbdb271 100644 --- a/plugins/builtin/source/lang/en_US.cpp +++ b/plugins/builtin/source/lang/en_US.cpp @@ -276,7 +276,11 @@ namespace hex::plugin::builtin { { "hex.builtin.view.pattern_editor.open_pattern", "Open pattern" }, { "hex.builtin.view.pattern_editor.evaluating", "Evaluating..." }, { "hex.builtin.view.pattern_editor.auto", "Auto evaluate" }, + { "hex.builtin.view.pattern_editor.console", "Console" }, { "hex.builtin.view.pattern_editor.env_vars", "Environment Variables" }, + { "hex.builtin.view.pattern_editor.settings", "Settings" }, + { "hex.builtin.view.pattern_editor.dangerous_function.name", "Allow dangerous function?" }, + { "hex.builtin.view.pattern_editor.dangerous_function.desc", "This pattern tried to call a dangerous function.\nAre you sure you want to trust this pattern?" }, { "hex.builtin.view.pattern_data.name", "Pattern Data" }, { "hex.builtin.view.pattern_data.var_name", "Name" }, diff --git a/plugins/builtin/source/lang/it_IT.cpp b/plugins/builtin/source/lang/it_IT.cpp index a1e8723f8..99e9e6669 100644 --- a/plugins/builtin/source/lang/it_IT.cpp +++ b/plugins/builtin/source/lang/it_IT.cpp @@ -273,7 +273,11 @@ namespace hex::plugin::builtin { { "hex.builtin.view.pattern_editor.open_pattern", "Apri pattern" }, { "hex.builtin.view.pattern_editor.evaluating", "Valutazione..." }, { "hex.builtin.view.pattern_editor.auto", "Auto valutazione" }, + //{ "hex.builtin.view.pattern_editor.console", "Console" }, //{ "hex.builtin.view.pattern_editor.env_vars", "Environment Variables" }, + //{ "hex.builtin.view.pattern_editor.settings", "Settings" }, + //{ "hex.builtin.view.pattern_editor.dangerous_function.name", "Allow dangerous function?" }, + //{ "hex.builtin.view.pattern_editor.dangerous_function.desc", "This pattern tried to call a dangerous function.\nAre you sure you want to trust this pattern?" }, { "hex.builtin.view.pattern_data.name", "Dati dei Pattern" }, { "hex.builtin.view.pattern_data.var_name", "Nome" }, diff --git a/plugins/builtin/source/lang/zh_CN.cpp b/plugins/builtin/source/lang/zh_CN.cpp index 59ba09d05..ac07078b0 100644 --- a/plugins/builtin/source/lang/zh_CN.cpp +++ b/plugins/builtin/source/lang/zh_CN.cpp @@ -273,7 +273,11 @@ namespace hex::plugin::builtin { { "hex.builtin.view.pattern_editor.open_pattern", "打开模式" }, { "hex.builtin.view.pattern_editor.evaluating", "计算中..." }, { "hex.builtin.view.pattern_editor.auto", "自动计算" }, + //{ "hex.builtin.view.pattern_editor.console", "Console" }, //{ "hex.builtin.view.pattern_editor.env_vars", "Environment Variables" }, + //{ "hex.builtin.view.pattern_editor.settings", "Settings" }, + //{ "hex.builtin.view.pattern_editor.dangerous_function.name", "Allow dangerous function?" }, + //{ "hex.builtin.view.pattern_editor.dangerous_function.desc", "This pattern tried to call a dangerous function.\nAre you sure you want to trust this pattern?" }, { "hex.builtin.view.pattern_data.name", "模式数据" }, { "hex.builtin.view.pattern_data.var_name", "名称" }, diff --git a/plugins/libimhex/include/hex/api/content_registry.hpp b/plugins/libimhex/include/hex/api/content_registry.hpp index 96f3b5bb5..3f603a652 100644 --- a/plugins/libimhex/include/hex/api/content_registry.hpp +++ b/plugins/libimhex/include/hex/api/content_registry.hpp @@ -94,9 +94,10 @@ namespace hex { struct Function { u32 parameterCount; Callback func; + bool dangerous; }; - void add(const Namespace &ns, const std::string &name, u32 parameterCount, const Callback &func); + void add(const Namespace &ns, const std::string &name, u32 parameterCount, const Callback &func, bool dangerous = false); std::map& getEntries(); } diff --git a/plugins/libimhex/include/hex/pattern_language/ast_node.hpp b/plugins/libimhex/include/hex/pattern_language/ast_node.hpp index 03f71a2ac..49b3c7dc0 100644 --- a/plugins/libimhex/include/hex/pattern_language/ast_node.hpp +++ b/plugins/libimhex/include/hex/pattern_language/ast_node.hpp @@ -6,8 +6,10 @@ #include #include +#include #include #include +#include #include #include @@ -1899,7 +1901,23 @@ namespace hex::pl { } try { - auto result = functions[this->m_functionName].func(evaluator, evaluatedParams); + auto &function = functions[this->m_functionName]; + + if (function.dangerous && evaluator->getDangerousFunctionPermission() != DangerousFunctionPermission::Allow) { + evaluator->dangerousFunctionCalled(); + + while (evaluator->getDangerousFunctionPermission() == DangerousFunctionPermission::Ask) { + using namespace std::literals::chrono_literals; + + std::this_thread::sleep_for(100ms); + } + + if (evaluator->getDangerousFunctionPermission() == DangerousFunctionPermission::Deny) { + LogConsole::abortEvaluation(hex::format("calling of dangerous function '{}' is not allowed", this->m_functionName), this); + } + } + + auto result = function.func(evaluator, evaluatedParams); if (result.has_value()) return new ASTNodeLiteral(result.value()); diff --git a/plugins/libimhex/include/hex/pattern_language/evaluator.hpp b/plugins/libimhex/include/hex/pattern_language/evaluator.hpp index 17a617a4f..4396c459b 100644 --- a/plugins/libimhex/include/hex/pattern_language/evaluator.hpp +++ b/plugins/libimhex/include/hex/pattern_language/evaluator.hpp @@ -15,6 +15,12 @@ namespace hex::prv { class Provider; } namespace hex::pl { + enum class DangerousFunctionPermission { + Ask, + Deny, + Allow + }; + class PatternData; class PatternCreationLimiter; class ASTNode; @@ -181,6 +187,25 @@ namespace hex::pl { this->m_envVariables[name] = value; } + [[nodiscard]] + bool hasDangerousFunctionBeenCalled() const { + return this->m_dangerousFunctionCalled; + } + + void dangerousFunctionCalled() { + this->m_dangerousFunctionCalled = true; + } + + void allowDangerousFunctions(bool allow) { + this->m_allowDangerousFunctions = allow ? DangerousFunctionPermission::Allow : DangerousFunctionPermission::Deny; + this->m_dangerousFunctionCalled = false; + } + + [[nodiscard]] + DangerousFunctionPermission getDangerousFunctionPermission() const { + return this->m_allowDangerousFunctions; + } + private: void patternCreated(); @@ -210,6 +235,9 @@ namespace hex::pl { std::map m_inVariables; std::map m_outVariables; + std::atomic m_dangerousFunctionCalled = false; + std::atomic m_allowDangerousFunctions = DangerousFunctionPermission::Ask; + friend class PatternCreationLimiter; }; diff --git a/plugins/libimhex/include/hex/pattern_language/pattern_language.hpp b/plugins/libimhex/include/hex/pattern_language/pattern_language.hpp index 8c1b29efc..89bb80733 100644 --- a/plugins/libimhex/include/hex/pattern_language/pattern_language.hpp +++ b/plugins/libimhex/include/hex/pattern_language/pattern_language.hpp @@ -53,6 +53,10 @@ namespace hex::pl { [[nodiscard]] u32 getMaximumPatternCount(); + [[nodiscard]] + bool hasDangerousFunctionBeenCalled() const; + void allowDangerousFunctions(bool allow); + private: Preprocessor *m_preprocessor; Lexer *m_lexer; diff --git a/plugins/libimhex/source/api/content_registry.cpp b/plugins/libimhex/source/api/content_registry.cpp index ce6c045ff..2cb9365c3 100644 --- a/plugins/libimhex/source/api/content_registry.cpp +++ b/plugins/libimhex/source/api/content_registry.cpp @@ -167,14 +167,14 @@ namespace hex { /* Pattern Language Functions */ - void ContentRegistry::PatternLanguageFunctions::add(const Namespace &ns, const std::string &name, u32 parameterCount, const ContentRegistry::PatternLanguageFunctions::Callback &func) { + void ContentRegistry::PatternLanguageFunctions::add(const Namespace &ns, const std::string &name, u32 parameterCount, const ContentRegistry::PatternLanguageFunctions::Callback &func, bool dangerous) { std::string functionName; for (auto &scope : ns) functionName += scope + "::"; functionName += name; - getEntries()[functionName] = Function { parameterCount, func }; + getEntries()[functionName] = Function { parameterCount, func, dangerous }; } std::map& ContentRegistry::PatternLanguageFunctions::getEntries() { diff --git a/plugins/libimhex/source/pattern_language/evaluator.cpp b/plugins/libimhex/source/pattern_language/evaluator.cpp index 5f994931c..56f728c28 100644 --- a/plugins/libimhex/source/pattern_language/evaluator.cpp +++ b/plugins/libimhex/source/pattern_language/evaluator.cpp @@ -127,6 +127,11 @@ namespace hex::pl { this->m_scopes.clear(); this->m_aborted = false; + if (this->m_allowDangerousFunctions == DangerousFunctionPermission::Deny) + this->m_allowDangerousFunctions = DangerousFunctionPermission::Ask; + + this->m_dangerousFunctionCalled = false; + ON_SCOPE_EXIT { this->m_envVariables.clear(); }; diff --git a/plugins/libimhex/source/pattern_language/pattern_language.cpp b/plugins/libimhex/source/pattern_language/pattern_language.cpp index e5f11dadd..2fb22fb35 100644 --- a/plugins/libimhex/source/pattern_language/pattern_language.cpp +++ b/plugins/libimhex/source/pattern_language/pattern_language.cpp @@ -185,4 +185,13 @@ namespace hex::pl { return this->m_evaluator->getPatternLimit(); } + + void PatternLanguage::allowDangerousFunctions(bool allow) { + this->m_evaluator->allowDangerousFunctions(allow); + } + + bool PatternLanguage::hasDangerousFunctionBeenCalled() const { + return this->m_evaluator->hasDangerousFunctionBeenCalled(); + } + } \ No newline at end of file