patterns: Disallow calling of dangerous functions by default
Closes #330
This commit is contained in:
parent
0efb226c2f
commit
376cb01a16
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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" },
|
||||
|
@ -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" },
|
||||
|
@ -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" },
|
||||
|
@ -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", "名称" },
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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() {
|
||||
|
@ -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();
|
||||
};
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user