patterns: Disallow calling of dangerous functions by default

Closes #330
This commit is contained in:
WerWolv 2021-12-19 12:32:15 +01:00
parent 0efb226c2f
commit 376cb01a16
13 changed files with 128 additions and 25 deletions

View File

@ -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<Token::Literal> {
@ -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<Token::Literal> {
@ -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<Token::Literal> {
@ -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<Token::Literal> {
@ -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<Token::Literal> {
@ -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<Token::Literal> {
@ -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<Token::Literal> {
@ -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<Token::Literal> {
@ -388,7 +388,7 @@ namespace hex::plugin::builtin {
openFiles[file].remove();
return { };
});
}, true);
}
}

View File

@ -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);

View File

@ -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" },

View File

@ -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" },

View File

@ -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" },

View File

@ -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", "名称" },

View File

@ -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<std::string, ContentRegistry::PatternLanguageFunctions::Function>& getEntries();
}

View File

@ -6,8 +6,10 @@
#include <algorithm>
#include <bit>
#include <chrono>
#include <optional>
#include <map>
#include <thread>
#include <variant>
#include <vector>
@ -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());

View File

@ -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<std::string, Token::Literal> m_inVariables;
std::map<std::string, size_t> m_outVariables;
std::atomic<bool> m_dangerousFunctionCalled = false;
std::atomic<DangerousFunctionPermission> m_allowDangerousFunctions = DangerousFunctionPermission::Ask;
friend class PatternCreationLimiter;
};

View File

@ -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;

View File

@ -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<std::string, ContentRegistry::PatternLanguageFunctions::Function>& ContentRegistry::PatternLanguageFunctions::getEntries() {

View File

@ -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();
};

View File

@ -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();
}
}