Skip to content

Commit

Permalink
patterns: Added recursion and array size limit pragma
Browse files Browse the repository at this point in the history
  • Loading branch information
WerWolv committed Sep 21, 2021
1 parent d1c0517 commit 7556428
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 5 deletions.
12 changes: 12 additions & 0 deletions plugins/libimhex/include/hex/pattern_language/ast_node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -833,6 +837,10 @@ namespace hex::pl {
}
} else if (auto whileStatement = dynamic_cast<ASTNodeWhileStatement*>(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));
Expand All @@ -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<u8> buffer(pattern->getSize());

Expand Down
35 changes: 33 additions & 2 deletions plugins/libimhex/include/hex/pattern_language/evaluator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <hex/pattern_language/log_console.hpp>
#include <hex/api/content_registry.hpp>

#include <hex/helpers/fmt.hpp>

namespace hex::prv { class Provider; }

namespace hex::pl {
Expand All @@ -27,8 +29,17 @@ namespace hex::pl {
}

struct Scope { PatternData *parent; std::vector<PatternData*>* scope; };
void pushScope(PatternData *parent, std::vector<PatternData*> &scope) { this->m_scopes.push_back({ parent, &scope }); }
void popScope() { this->m_scopes.pop_back(); }
void pushScope(PatternData *parent, std::vector<PatternData*> &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;

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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<Scope> m_scopes;
std::map<std::string, ContentRegistry::PatternLanguageFunctions::Function> m_customFunctions;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::pair<u32, std::string>> m_currError;
};
Expand Down
17 changes: 15 additions & 2 deletions plugins/libimhex/source/pattern_language/pattern_language.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
});

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

This comment has been minimized.

Copy link
@4g3v

4g3v Sep 26, 2021

Would be awesome if you could add a setting for the limit, this change broke a pattern I made.

This comment has been minimized.

Copy link
@WerWolv

WerWolv Sep 26, 2021

Author Owner

There is!
#pragma eval_depth 1234 for recursion depth and #pragma array_limit 1234 for the maximum array size.


for (auto &node : this->m_currAST)
delete node;
Expand All @@ -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()) {
Expand Down

0 comments on commit 7556428

Please sign in to comment.