diff --git a/plugins/libimhex/include/hex/lang/evaluator.hpp b/plugins/libimhex/include/hex/lang/evaluator.hpp index 687361fef..70dc6ac80 100644 --- a/plugins/libimhex/include/hex/lang/evaluator.hpp +++ b/plugins/libimhex/include/hex/lang/evaluator.hpp @@ -48,7 +48,7 @@ namespace hex::lang { std::vector*> m_currMembers; LogConsole m_console; - u32 m_recursionLimit = 16; + u32 m_recursionLimit; u32 m_currRecursionDepth; diff --git a/plugins/libimhex/include/hex/lang/pattern_language.hpp b/plugins/libimhex/include/hex/lang/pattern_language.hpp index e39c0b1c1..348b340eb 100644 --- a/plugins/libimhex/include/hex/lang/pattern_language.hpp +++ b/plugins/libimhex/include/hex/lang/pattern_language.hpp @@ -39,9 +39,9 @@ namespace hex::lang { Validator *m_validator; Evaluator *m_evaluator; - prv::Provider *m_provider; - std::endian m_defaultEndian; - u32 m_recursionLimit; + prv::Provider *m_provider = nullptr; + std::endian m_defaultEndian = std::endian::native; + u32 m_recursionLimit = 32; std::optional> m_currError; }; diff --git a/plugins/libimhex/include/hex/lang/preprocessor.hpp b/plugins/libimhex/include/hex/lang/preprocessor.hpp index 6982ddcd1..36df369f2 100644 --- a/plugins/libimhex/include/hex/lang/preprocessor.hpp +++ b/plugins/libimhex/include/hex/lang/preprocessor.hpp @@ -32,8 +32,8 @@ namespace hex::lang { std::unordered_map> m_pragmaHandlers; - std::set> m_defines; - std::set> m_pragmas; + std::set> m_defines; + std::set> m_pragmas; std::pair m_error; }; diff --git a/plugins/libimhex/source/lang/evaluator.cpp b/plugins/libimhex/source/lang/evaluator.cpp index 228a4b5e9..e65d31889 100644 --- a/plugins/libimhex/source/lang/evaluator.cpp +++ b/plugins/libimhex/source/lang/evaluator.cpp @@ -439,11 +439,17 @@ namespace hex::lang { this->m_currMembers.push_back(&memberPatterns); SCOPE_EXIT( this->m_currMembers.pop_back(); ); + 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 to increase the maximum", this->m_recursionLimit)); + auto startOffset = this->m_currOffset; for (auto &member : node->getMembers()) { this->evaluateMember(member, memberPatterns, true); } + this->m_currRecursionDepth--; + return this->evaluateAttributes(node, new PatternDataStruct(startOffset, this->m_currOffset - startOffset, memberPatterns)); } @@ -455,10 +461,16 @@ namespace hex::lang { auto startOffset = this->m_currOffset; + 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 to increase the maximum", this->m_recursionLimit)); + for (auto &member : node->getMembers()) { this->evaluateMember(member, memberPatterns, false); } + this->m_currRecursionDepth--; + size_t size = 0; for (const auto &pattern : memberPatterns) size = std::max(size, pattern->getSize()); @@ -538,10 +550,6 @@ 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 to increase the maximum", this->m_recursionLimit)); - if (auto builtinTypeNode = dynamic_cast(type); builtinTypeNode != nullptr) return this->evaluateBuiltinType(builtinTypeNode); else if (auto typeDeclNode = dynamic_cast(type); typeDeclNode != nullptr) @@ -557,8 +565,6 @@ namespace hex::lang { else this->getConsole().abortEvaluation("type could not be evaluated"); - this->m_currRecursionDepth--; - if (!node->getName().empty()) pattern->setTypeName(node->getName().data()); diff --git a/plugins/libimhex/source/lang/preprocessor.cpp b/plugins/libimhex/source/lang/preprocessor.cpp index e46f42fde..c515c7fe1 100644 --- a/plugins/libimhex/source/lang/preprocessor.cpp +++ b/plugins/libimhex/source/lang/preprocessor.cpp @@ -119,7 +119,7 @@ namespace hex::lang { if (replaceValue.empty()) throwPreprocessorError("no value given in #define directive", lineNumber); - this->m_defines.emplace(defineName, replaceValue); + this->m_defines.emplace(defineName, replaceValue, lineNumber); } else if (code.substr(offset, 6) == "pragma") { offset += 6; @@ -151,7 +151,7 @@ namespace hex::lang { if (pragmaValue.empty()) throwPreprocessorError("missing value in #pragma directive", lineNumber); - this->m_pragmas.emplace(pragmaKey, pragmaValue); + this->m_pragmas.emplace(pragmaKey, pragmaValue, lineNumber); } else throwPreprocessorError("unknown preprocessor directive", lineNumber); } else if (code.substr(offset, 2) == "//") { @@ -181,13 +181,13 @@ namespace hex::lang { if (initialRun) { // Apply defines - std::vector> sortedDefines; + std::vector> sortedDefines; std::copy(this->m_defines.begin(), this->m_defines.end(), std::back_inserter(sortedDefines)); std::sort(sortedDefines.begin(), sortedDefines.end(), [](const auto &left, const auto &right) { - return left.first.size() > right.first.size(); + return std::get<0>(left).size() > std::get<0>(right).size(); }); - for (const auto &[define, value] : sortedDefines) { + for (const auto &[define, value, defineLine] : sortedDefines) { s32 index = 0; while((index = output.find(define, index)) != std::string::npos) { output.replace(index, define.length(), value); @@ -196,12 +196,12 @@ namespace hex::lang { } // Handle pragmas - for (const auto &[type, value] : this->m_pragmas) { + for (const auto &[type, value, pragmaLine] : this->m_pragmas) { if (this->m_pragmaHandlers.contains(type)) { if (!this->m_pragmaHandlers[type](value)) - throwPreprocessorError(hex::format("invalid value provided to '{0}' #pragma directive", type.c_str()), lineNumber); + throwPreprocessorError(hex::format("invalid value provided to '{0}' #pragma directive", type.c_str()), pragmaLine); } else - throwPreprocessorError(hex::format("no #pragma handler registered for type {0}", type.c_str()), lineNumber); + throwPreprocessorError(hex::format("no #pragma handler registered for type {0}", type.c_str()), pragmaLine); } } } catch (PreprocessorError &e) {