mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-04-02 05:27:41 -05:00
patterns: Added button to abort evaluation
This commit is contained in:
@@ -516,7 +516,10 @@ namespace hex::pl {
|
||||
|
||||
FunctionResult execute(Evaluator *evaluator) override {
|
||||
|
||||
u64 loopIterations = 0;
|
||||
while (evaluateCondition(evaluator)) {
|
||||
evaluator->handleAbort();
|
||||
|
||||
auto variables = *evaluator->getScope(0).scope;
|
||||
u32 startVariableCount = variables.size();
|
||||
ON_SCOPE_EXIT {
|
||||
@@ -538,6 +541,12 @@ namespace hex::pl {
|
||||
return { true, result };
|
||||
}
|
||||
}
|
||||
|
||||
loopIterations++;
|
||||
if (loopIterations >= evaluator->getLoopLimit())
|
||||
LogConsole::abortEvaluation(hex::format("loop iterations exceeded limit of {}", evaluator->getLoopLimit()), this);
|
||||
|
||||
evaluator->handleAbort();
|
||||
}
|
||||
|
||||
return { false, { } };
|
||||
@@ -807,6 +816,7 @@ namespace hex::pl {
|
||||
while (whileStatement->evaluateCondition(evaluator)) {
|
||||
entryCount++;
|
||||
evaluator->dataOffset() += templatePattern->getSize();
|
||||
evaluator->handleAbort();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -829,6 +839,7 @@ namespace hex::pl {
|
||||
}
|
||||
|
||||
if (reachedEnd) break;
|
||||
evaluator->handleAbort();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -901,6 +912,8 @@ namespace hex::pl {
|
||||
entries.push_back(pattern);
|
||||
|
||||
size += pattern->getSize();
|
||||
|
||||
evaluator->handleAbort();
|
||||
}
|
||||
} else if (auto whileStatement = dynamic_cast<ASTNodeWhileStatement*>(sizeNode)) {
|
||||
while (whileStatement->evaluateCondition(evaluator)) {
|
||||
@@ -917,6 +930,8 @@ namespace hex::pl {
|
||||
|
||||
entryCount++;
|
||||
size += pattern->getSize();
|
||||
|
||||
evaluator->handleAbort();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -951,6 +966,7 @@ namespace hex::pl {
|
||||
}
|
||||
|
||||
if (reachedEnd) break;
|
||||
evaluator->handleAbort();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1380,6 +1396,10 @@ namespace hex::pl {
|
||||
|
||||
std::visit(overloaded {
|
||||
[&](std::string &assignmentValue) { },
|
||||
[&](s128 assignmentValue) {
|
||||
std::memcpy(&value, &assignmentValue, pattern->getSize());
|
||||
value = hex::signExtend(pattern->getSize() * 8, value);
|
||||
},
|
||||
[&](auto &&assignmentValue) { std::memcpy(&value, &assignmentValue, pattern->getSize()); }
|
||||
}, literal);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <bit>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
@@ -31,8 +32,10 @@ namespace hex::pl {
|
||||
|
||||
struct Scope { PatternData *parent; std::vector<PatternData*>* scope; };
|
||||
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));
|
||||
if (this->m_scopes.size() > this->getEvaluationDepth())
|
||||
LogConsole::abortEvaluation(hex::format("evaluation depth exceeded set limit of {}", this->getEvaluationDepth()));
|
||||
|
||||
this->handleAbort();
|
||||
|
||||
this->m_scopes.push_back({ parent, &scope });
|
||||
}
|
||||
@@ -70,38 +73,47 @@ namespace hex::pl {
|
||||
return this->m_defaultEndian;
|
||||
}
|
||||
|
||||
void setEvaluationDepth(u32 evalDepth) {
|
||||
void setEvaluationDepth(u64 evalDepth) {
|
||||
this->m_evalDepth = evalDepth;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
u32 getEvaluationDepth() const {
|
||||
u64 getEvaluationDepth() const {
|
||||
return this->m_evalDepth;
|
||||
}
|
||||
|
||||
void setArrayLimit(u32 arrayLimit) {
|
||||
void setArrayLimit(u64 arrayLimit) {
|
||||
this->m_arrayLimit = arrayLimit;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
u32 getArrayLimit() const {
|
||||
u64 getArrayLimit() const {
|
||||
return this->m_arrayLimit;
|
||||
}
|
||||
|
||||
void setPatternLimit(u32 limit) {
|
||||
void setPatternLimit(u64 limit) {
|
||||
this->m_patternLimit = limit;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
u32 getPatternLimit() {
|
||||
u64 getPatternLimit() {
|
||||
return this->m_patternLimit;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
u32 getPatternCount() {
|
||||
u64 getPatternCount() {
|
||||
return this->m_currPatternCount;
|
||||
}
|
||||
|
||||
void setLoopLimit(u64 limit) {
|
||||
this->m_loopLimit = limit;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
u64 getLoopLimit() {
|
||||
return this->m_loopLimit;
|
||||
}
|
||||
|
||||
u64& dataOffset() { return this->m_currOffset; }
|
||||
|
||||
bool addCustomFunction(const std::string &name, u32 numParams, const ContentRegistry::PatternLanguageFunctions::Callback &function) {
|
||||
@@ -123,6 +135,15 @@ namespace hex::pl {
|
||||
void createVariable(const std::string &name, ASTNode *type, const std::optional<Token::Literal> &value = std::nullopt);
|
||||
void setVariable(const std::string &name, const Token::Literal& value);
|
||||
|
||||
void abort() {
|
||||
this->m_aborted = true;
|
||||
}
|
||||
|
||||
void handleAbort() {
|
||||
if (this->m_aborted)
|
||||
LogConsole::abortEvaluation("evaluation aborted by user");
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void patternCreated();
|
||||
@@ -134,11 +155,14 @@ namespace hex::pl {
|
||||
LogConsole m_console;
|
||||
|
||||
std::endian m_defaultEndian = std::endian::native;
|
||||
u32 m_evalDepth;
|
||||
u32 m_arrayLimit;
|
||||
u32 m_patternLimit;
|
||||
u64 m_evalDepth;
|
||||
u64 m_arrayLimit;
|
||||
u64 m_patternLimit;
|
||||
u64 m_loopLimit;
|
||||
|
||||
u32 m_currPatternCount;
|
||||
u64 m_currPatternCount;
|
||||
|
||||
std::atomic<bool> m_aborted;
|
||||
|
||||
std::vector<Scope> m_scopes;
|
||||
std::map<std::string, ContentRegistry::PatternLanguageFunctions::Function> m_customFunctions;
|
||||
|
||||
@@ -31,6 +31,8 @@ namespace hex::pl {
|
||||
std::optional<std::vector<PatternData*>> executeString(prv::Provider *provider, const std::string &string);
|
||||
std::optional<std::vector<PatternData*>> executeFile(prv::Provider *provider, const std::string &path);
|
||||
|
||||
void abort();
|
||||
|
||||
const std::vector<std::pair<LogConsole::Level, std::string>>& getConsoleLog();
|
||||
const std::optional<std::pair<u32, std::string>>& getError();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user