From 755642862f18475c7ee818429ac5a2537acc6a4a Mon Sep 17 00:00:00 2001 From: WerWolv Date: Wed, 22 Sep 2021 00:45:04 +0200 Subject: [PATCH] patterns: Added recursion and array size limit pragma --- .../include/hex/pattern_language/ast_node.hpp | 12 +++++++ .../hex/pattern_language/evaluator.hpp | 35 +++++++++++++++++-- .../hex/pattern_language/pattern_language.hpp | 3 +- .../pattern_language/pattern_language.cpp | 17 +++++++-- 4 files changed, 62 insertions(+), 5 deletions(-) diff --git a/plugins/libimhex/include/hex/pattern_language/ast_node.hpp b/plugins/libimhex/include/hex/pattern_language/ast_node.hpp index bb03d713a..29bc4d110 100644 --- a/plugins/libimhex/include/hex/pattern_language/ast_node.hpp +++ b/plugins/libimhex/include/hex/pattern_language/ast_node.hpp @@ -821,6 +821,10 @@ namespace hex::pl { [](auto &&size) -> u128 { return size; } }, literal->getValue()); + auto limit = evaluator->getArrayLimit(); + if (entryCount > limit) + LogConsole::abortEvaluation(hex::format("array grew past set limit of {}", limit), this); + for (u64 i = 0; i < entryCount; i++) { auto pattern = this->m_type->createPatterns(evaluator).front(); @@ -833,6 +837,10 @@ namespace hex::pl { } } else if (auto whileStatement = dynamic_cast(sizeNode)) { while (whileStatement->evaluateCondition(evaluator)) { + auto limit = evaluator->getArrayLimit(); + if (entryCount > limit) + LogConsole::abortEvaluation(hex::format("array grew past set limit of {}", limit), this); + auto pattern = this->m_type->createPatterns(evaluator).front(); pattern->setVariableName(hex::format("[{}]", entryCount)); @@ -846,6 +854,10 @@ namespace hex::pl { } } else { while (true) { + auto limit = evaluator->getArrayLimit(); + if (entryCount > limit) + LogConsole::abortEvaluation(hex::format("array grew past set limit of {}", limit), this); + auto pattern = this->m_type->createPatterns(evaluator).front(); std::vector buffer(pattern->getSize()); diff --git a/plugins/libimhex/include/hex/pattern_language/evaluator.hpp b/plugins/libimhex/include/hex/pattern_language/evaluator.hpp index e0241b9bd..c8280ca0c 100644 --- a/plugins/libimhex/include/hex/pattern_language/evaluator.hpp +++ b/plugins/libimhex/include/hex/pattern_language/evaluator.hpp @@ -8,6 +8,8 @@ #include #include +#include + namespace hex::prv { class Provider; } namespace hex::pl { @@ -27,8 +29,17 @@ namespace hex::pl { } struct Scope { PatternData *parent; std::vector* scope; }; - void pushScope(PatternData *parent, std::vector &scope) { this->m_scopes.push_back({ parent, &scope }); } - void popScope() { this->m_scopes.pop_back(); } + void pushScope(PatternData *parent, std::vector &scope) { + if (this->m_scopes.size() > this->m_evalDepth) + LogConsole::abortEvaluation(hex::format("recursion limit of {} reached", this->m_evalDepth)); + + this->m_scopes.push_back({ parent, &scope }); + } + + void popScope() { + this->m_scopes.pop_back(); + } + const Scope& getScope(s32 index) { static Scope empty; @@ -58,6 +69,24 @@ namespace hex::pl { return this->m_defaultEndian; } + void setEvaluationDepth(u32 evalDepth) { + this->m_evalDepth = evalDepth; + } + + [[nodiscard]] + u32 getEvaluationDepth() const { + return this->m_evalDepth; + } + + void setArrayLimit(u32 arrayLimit) { + this->m_arrayLimit = arrayLimit; + } + + [[nodiscard]] + u32 getArrayLimit() const { + return this->m_arrayLimit; + } + u64& dataOffset() { return this->m_currOffset; } bool addCustomFunction(const std::string &name, u32 numParams, const ContentRegistry::PatternLanguageFunctions::Callback &function) { @@ -86,6 +115,8 @@ namespace hex::pl { LogConsole m_console; std::endian m_defaultEndian = std::endian::native; + u32 m_evalDepth; + u32 m_arrayLimit; std::vector m_scopes; std::map m_customFunctions; diff --git a/plugins/libimhex/include/hex/pattern_language/pattern_language.hpp b/plugins/libimhex/include/hex/pattern_language/pattern_language.hpp index 0b1814efe..15044671b 100644 --- a/plugins/libimhex/include/hex/pattern_language/pattern_language.hpp +++ b/plugins/libimhex/include/hex/pattern_language/pattern_language.hpp @@ -45,7 +45,8 @@ namespace hex::pl { prv::Provider *m_provider = nullptr; std::endian m_defaultEndian = std::endian::native; - u32 m_recursionLimit = 32; + u32 m_evalDepth; + u32 m_arrayLimit; std::optional> m_currError; }; diff --git a/plugins/libimhex/source/pattern_language/pattern_language.cpp b/plugins/libimhex/source/pattern_language/pattern_language.cpp index 4f47c7533..bb80ae6a7 100644 --- a/plugins/libimhex/source/pattern_language/pattern_language.cpp +++ b/plugins/libimhex/source/pattern_language/pattern_language.cpp @@ -43,7 +43,17 @@ namespace hex::pl { if (limit <= 0) return false; - this->m_recursionLimit = limit; + this->m_evalDepth = limit; + return true; + }); + + this->m_preprocessor->addPragmaHandler("array_limit", [this](std::string value) { + auto limit = strtol(value.c_str(), nullptr, 0); + + if (limit <= 0) + return false; + + this->m_arrayLimit = limit; return true; }); @@ -69,6 +79,8 @@ namespace hex::pl { this->m_currError.reset(); this->m_evaluator->getConsole().clear(); this->m_evaluator->setProvider(provider); + this->m_evalDepth = 32; + this->m_arrayLimit = 0x1000; for (auto &node : this->m_currAST) delete node; @@ -81,7 +93,8 @@ namespace hex::pl { } this->m_evaluator->setDefaultEndian(this->m_defaultEndian); - // this->m_evaluator->setRecursionLimit(this->m_recursionLimit); + this->m_evaluator->setEvaluationDepth(this->m_evalDepth); + this->m_evaluator->setArrayLimit(this->m_arrayLimit); auto tokens = this->m_lexer->lex(preprocessedCode.value()); if (!tokens.has_value()) {