mirror of https://github.com/WerWolv/ImHex.git
nodes/patterns: Fixed crashes when recursion occurred
This commit is contained in:
parent
d4265f16eb
commit
8423f78586
|
@ -2,6 +2,9 @@
|
|||
|
||||
#include <hex/data_processor/attribute.hpp>
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace hex::dp {
|
||||
|
||||
class Node {
|
||||
|
@ -31,10 +34,15 @@ namespace hex::dp {
|
|||
attribute.getOutputData().reset();
|
||||
}
|
||||
|
||||
void resetProcessedInputs() {
|
||||
this->m_processedInputs.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
u32 m_id;
|
||||
std::string m_unlocalizedName;
|
||||
std::vector<Attribute> m_attributes;
|
||||
std::set<u32> m_processedInputs;
|
||||
prv::Overlay *m_overlay = nullptr;
|
||||
|
||||
Attribute* getConnectedInputAttribute(u32 index) {
|
||||
|
@ -49,6 +57,12 @@ namespace hex::dp {
|
|||
return connectedAttribute.begin()->second;
|
||||
}
|
||||
|
||||
void markInputProcessed(u32 index) {
|
||||
const auto &[iter, inserted] = this->m_processedInputs.insert(index);
|
||||
if (!inserted)
|
||||
throwNodeError("Recursion detected!");
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
[[noreturn]] void throwNodeError(std::string_view message) {
|
||||
|
@ -64,6 +78,7 @@ namespace hex::dp {
|
|||
if (attribute->getType() != Attribute::Type::Buffer)
|
||||
throwNodeError("Tried to read buffer from non-buffer attribute");
|
||||
|
||||
markInputProcessed(index);
|
||||
attribute->getParentNode()->process();
|
||||
|
||||
auto &outputData = attribute->getOutputData();
|
||||
|
@ -83,6 +98,7 @@ namespace hex::dp {
|
|||
if (attribute->getType() != Attribute::Type::Integer)
|
||||
throwNodeError("Tried to read integer from non-integer attribute");
|
||||
|
||||
markInputProcessed(index);
|
||||
attribute->getParentNode()->process();
|
||||
|
||||
auto &outputData = attribute->getOutputData();
|
||||
|
@ -105,6 +121,7 @@ namespace hex::dp {
|
|||
if (attribute->getType() != Attribute::Type::Float)
|
||||
throwNodeError("Tried to read float from non-float attribute");
|
||||
|
||||
markInputProcessed(index);
|
||||
attribute->getParentNode()->process();
|
||||
|
||||
auto &outputData = attribute->getOutputData();
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace hex::lang {
|
|||
LogConsole& getConsole() { return this->m_console; }
|
||||
|
||||
void setDefaultEndian(std::endian endian) { this->m_defaultDataEndian = endian; }
|
||||
void setRecursionLimit(u32 limit) { this->m_recursionLimit = limit; }
|
||||
void setProvider(prv::Provider *provider) { this->m_provider = provider; }
|
||||
[[nodiscard]] std::endian getCurrentEndian() const { return this->m_endianStack.back(); }
|
||||
|
||||
|
@ -47,6 +48,8 @@ namespace hex::lang {
|
|||
std::vector<std::vector<PatternData*>*> m_currMembers;
|
||||
LogConsole m_console;
|
||||
|
||||
u32 m_recursionLimit = 16;
|
||||
u32 m_currRecursionDepth;
|
||||
|
||||
|
||||
ASTNodeIntegerLiteral* evaluateScopeResolution(ASTNodeScopeResolution *node);
|
||||
|
|
|
@ -41,6 +41,7 @@ namespace hex::lang {
|
|||
|
||||
prv::Provider *m_provider;
|
||||
std::endian m_defaultEndian;
|
||||
u32 m_recursionLimit;
|
||||
|
||||
std::optional<std::pair<u32, std::string>> m_currError;
|
||||
};
|
||||
|
|
|
@ -538,6 +538,10 @@ namespace hex::lang {
|
|||
|
||||
PatternData *pattern;
|
||||
|
||||
this->m_currRecursionDepth++;
|
||||
if (this->m_currRecursionDepth > this->m_recursionLimit)
|
||||
this->getConsole().abortEvaluation(hex::format("evaluation depth exceeds maximum of {0}. Use #pragma eval_depth <depth> to increase the maximum", this->m_recursionLimit));
|
||||
|
||||
if (auto builtinTypeNode = dynamic_cast<ASTNodeBuiltinType*>(type); builtinTypeNode != nullptr)
|
||||
return this->evaluateBuiltinType(builtinTypeNode);
|
||||
else if (auto typeDeclNode = dynamic_cast<ASTNodeTypeDecl*>(type); typeDeclNode != nullptr)
|
||||
|
@ -553,6 +557,8 @@ namespace hex::lang {
|
|||
else
|
||||
this->getConsole().abortEvaluation("type could not be evaluated");
|
||||
|
||||
this->m_currRecursionDepth--;
|
||||
|
||||
if (!node->getName().empty())
|
||||
pattern->setTypeName(node->getName().data());
|
||||
|
||||
|
@ -752,6 +758,7 @@ namespace hex::lang {
|
|||
try {
|
||||
for (const auto& node : ast) {
|
||||
this->m_endianStack.push_back(this->m_defaultDataEndian);
|
||||
this->m_currRecursionDepth = 0;
|
||||
|
||||
if (auto variableDeclNode = dynamic_cast<ASTNodeVariableDecl*>(node); variableDeclNode != nullptr) {
|
||||
this->m_globalMembers.push_back(this->evaluateVariable(variableDeclNode));
|
||||
|
|
|
@ -33,6 +33,16 @@ namespace hex::lang {
|
|||
} else
|
||||
return false;
|
||||
});
|
||||
|
||||
this->m_preprocessor->addPragmaHandler("eval_depth", [this](std::string value) {
|
||||
auto limit = strtol(value.c_str(), nullptr, 0);
|
||||
|
||||
if (limit <= 0)
|
||||
return false;
|
||||
|
||||
this->m_recursionLimit = limit;
|
||||
return true;
|
||||
});
|
||||
this->m_preprocessor->addDefaultPragmaHandlers();
|
||||
}
|
||||
|
||||
|
@ -56,6 +66,9 @@ namespace hex::lang {
|
|||
return { };
|
||||
}
|
||||
|
||||
this->m_evaluator->setDefaultEndian(this->m_defaultEndian);
|
||||
this->m_evaluator->setRecursionLimit(this->m_recursionLimit);
|
||||
|
||||
auto tokens = this->m_lexer->lex(preprocessedCode.value());
|
||||
if (!tokens.has_value()) {
|
||||
this->m_currError = this->m_lexer->getError();
|
||||
|
|
|
@ -117,6 +117,10 @@ namespace hex {
|
|||
try {
|
||||
for (auto &endNode : this->m_endNodes) {
|
||||
endNode->resetOutputData();
|
||||
|
||||
for (auto &node : this->m_nodes)
|
||||
node->resetProcessedInputs();
|
||||
|
||||
endNode->process();
|
||||
}
|
||||
} catch (dp::Node::NodeError &e) {
|
||||
|
|
Loading…
Reference in New Issue