From d69eb440d89e7b7082eff216a179a87922520380 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Sat, 22 Jan 2022 13:44:00 +0100 Subject: [PATCH] pattern: Fixed memory leak when using conditionals in structs --- .../include/hex/pattern_language/ast_node.hpp | 391 +++++++++--------- .../source/pattern_language/evaluator.cpp | 2 +- .../source/pattern_language/parser.cpp | 14 +- 3 files changed, 212 insertions(+), 195 deletions(-) diff --git a/lib/libimhex/include/hex/pattern_language/ast_node.hpp b/lib/libimhex/include/hex/pattern_language/ast_node.hpp index 0e381f8c2..e2ab1d659 100644 --- a/lib/libimhex/include/hex/pattern_language/ast_node.hpp +++ b/lib/libimhex/include/hex/pattern_language/ast_node.hpp @@ -124,7 +124,7 @@ namespace hex::pl { }; class ASTNodeMathematicalExpression : public ASTNode { - #define FLOAT_BIT_OPERATION(name) \ +#define FLOAT_BIT_OPERATION(name) \ auto name(hex::floating_point auto left, auto right) const { LogConsole::abortEvaluation("invalid floating point operation", this); return 0; } \ auto name(auto left, hex::floating_point auto right) const { LogConsole::abortEvaluation("invalid floating point operation", this); return 0; } \ auto name(hex::floating_point auto left, hex::floating_point auto right) const { LogConsole::abortEvaluation("invalid floating point operation", this); return 0; } \ @@ -158,7 +158,7 @@ namespace hex::pl { return left % right; } - #undef FLOAT_BIT_OPERATION +#undef FLOAT_BIT_OPERATION public: ASTNodeMathematicalExpression(ASTNode *left, ASTNode *right, Token::Operator op) : ASTNode(), m_left(left), m_right(right), m_operator(op) { } @@ -187,63 +187,55 @@ namespace hex::pl { ON_SCOPE_EXIT { delete left; delete right; }; return std::visit(overloaded { - // TODO: :notlikethis: - [this](u128 left, PatternData * const &right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, - [this](s128 left, PatternData * const &right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, - [this](double left, PatternData * const &right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, - [this](char left, PatternData * const &right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, - [this](bool left, PatternData * const &right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, - [this](std::string left, PatternData * const &right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, - [this](PatternData * const &left, u128 right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, - [this](PatternData * const &left, s128 right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, - [this](PatternData * const &left, double right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, - [this](PatternData * const &left, char right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, - [this](PatternData * const &left, bool right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, - [this](PatternData * const &left, std::string right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, - [this](PatternData * const &left, PatternData *right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, + // TODO: :notlikethis: + [this](u128 left, PatternData * const &right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, + [this](s128 left, PatternData * const &right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, + [this](double left, PatternData * const &right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, + [this](char left, PatternData * const &right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, + [this](bool left, PatternData * const &right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, + [this](std::string left, PatternData * const &right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, + [this](PatternData * const &left, u128 right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, + [this](PatternData * const &left, s128 right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, + [this](PatternData * const &left, double right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, + [this](PatternData * const &left, char right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, + [this](PatternData * const &left, bool right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, + [this](PatternData * const &left, std::string right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, + [this](PatternData * const &left, PatternData *right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, - [this](auto&& left, std::string right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, - [this](std::string left, auto&& right) -> ASTNode* { - switch (this->getOperator()) { - case Token::Operator::Star: { - std::string result; - for (auto i = 0; i < right; i++) - result += left; - return new ASTNodeLiteral(result); + [this](auto&& left, std::string right) -> ASTNode* { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); }, + [this](std::string left, auto&& right) -> ASTNode* { + switch (this->getOperator()) { + case Token::Operator::Star: { + std::string result; + for (auto i = 0; i < right; i++) + result += left; + return new ASTNodeLiteral(result); + } + default: + LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); } - default: - LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); - } - }, - [this](std::string left, std::string right) -> ASTNode* { - switch (this->getOperator()) { - case Token::Operator::Plus: - return new ASTNodeLiteral(left + right); - case Token::Operator::BoolEquals: - return new ASTNodeLiteral(left == right); - case Token::Operator::BoolNotEquals: - return new ASTNodeLiteral(left != right); - case Token::Operator::BoolGreaterThan: - return new ASTNodeLiteral(left > right); - case Token::Operator::BoolLessThan: - return new ASTNodeLiteral(left < right); - case Token::Operator::BoolGreaterThanOrEquals: - return new ASTNodeLiteral(left >= right); - case Token::Operator::BoolLessThanOrEquals: - return new ASTNodeLiteral(left <= right); - default: - LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); - } - }, - [this](std::string left, char right) -> ASTNode* { - switch (this->getOperator()) { - case Token::Operator::Plus: - return new ASTNodeLiteral(left + right); - default: - LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); - } - }, - [this](char left, std::string right) -> ASTNode* { + }, + [this](std::string left, std::string right) -> ASTNode* { + switch (this->getOperator()) { + case Token::Operator::Plus: + return new ASTNodeLiteral(left + right); + case Token::Operator::BoolEquals: + return new ASTNodeLiteral(left == right); + case Token::Operator::BoolNotEquals: + return new ASTNodeLiteral(left != right); + case Token::Operator::BoolGreaterThan: + return new ASTNodeLiteral(left > right); + case Token::Operator::BoolLessThan: + return new ASTNodeLiteral(left < right); + case Token::Operator::BoolGreaterThanOrEquals: + return new ASTNodeLiteral(left >= right); + case Token::Operator::BoolLessThanOrEquals: + return new ASTNodeLiteral(left <= right); + default: + LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); + } + }, + [this](std::string left, char right) -> ASTNode* { switch (this->getOperator()) { case Token::Operator::Plus: return new ASTNodeLiteral(left + right); @@ -251,56 +243,64 @@ namespace hex::pl { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); } }, - [this](auto &&left, auto &&right) -> ASTNode* { - switch (this->getOperator()) { - case Token::Operator::Plus: - return new ASTNodeLiteral(left + right); - case Token::Operator::Minus: - return new ASTNodeLiteral(left - right); - case Token::Operator::Star: - return new ASTNodeLiteral(left * right); - case Token::Operator::Slash: - if (right == 0) LogConsole::abortEvaluation("division by zero!", this); - return new ASTNodeLiteral(left / right); - case Token::Operator::Percent: - if (right == 0) LogConsole::abortEvaluation("division by zero!", this); - return new ASTNodeLiteral(modulus(left, right)); - case Token::Operator::ShiftLeft: - return new ASTNodeLiteral(shiftLeft(left, right)); - case Token::Operator::ShiftRight: - return new ASTNodeLiteral(shiftRight(left, right)); - case Token::Operator::BitAnd: - return new ASTNodeLiteral(bitAnd(left, right)); - case Token::Operator::BitXor: - return new ASTNodeLiteral(bitXor(left, right)); - case Token::Operator::BitOr: - return new ASTNodeLiteral(bitOr(left, right)); - case Token::Operator::BitNot: - return new ASTNodeLiteral(bitNot(left, right)); - case Token::Operator::BoolEquals: - return new ASTNodeLiteral(bool(left == right)); - case Token::Operator::BoolNotEquals: - return new ASTNodeLiteral(bool(left != right)); - case Token::Operator::BoolGreaterThan: - return new ASTNodeLiteral(bool(left > right)); - case Token::Operator::BoolLessThan: - return new ASTNodeLiteral(bool(left < right)); - case Token::Operator::BoolGreaterThanOrEquals: - return new ASTNodeLiteral(bool(left >= right)); - case Token::Operator::BoolLessThanOrEquals: - return new ASTNodeLiteral(bool(left <= right)); - case Token::Operator::BoolAnd: - return new ASTNodeLiteral(bool(left && right)); - case Token::Operator::BoolXor: - return new ASTNodeLiteral(bool(left && !right || !left && right)); - case Token::Operator::BoolOr: - return new ASTNodeLiteral(bool(left || right)); - case Token::Operator::BoolNot: - return new ASTNodeLiteral(bool(!right)); - default: - LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); + [this](char left, std::string right) -> ASTNode* { + switch (this->getOperator()) { + case Token::Operator::Plus: + return new ASTNodeLiteral(left + right); + default: + LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); + } + }, + [this](auto &&left, auto &&right) -> ASTNode* { + switch (this->getOperator()) { + case Token::Operator::Plus: + return new ASTNodeLiteral(left + right); + case Token::Operator::Minus: + return new ASTNodeLiteral(left - right); + case Token::Operator::Star: + return new ASTNodeLiteral(left * right); + case Token::Operator::Slash: + if (right == 0) LogConsole::abortEvaluation("division by zero!", this); + return new ASTNodeLiteral(left / right); + case Token::Operator::Percent: + if (right == 0) LogConsole::abortEvaluation("division by zero!", this); + return new ASTNodeLiteral(modulus(left, right)); + case Token::Operator::ShiftLeft: + return new ASTNodeLiteral(shiftLeft(left, right)); + case Token::Operator::ShiftRight: + return new ASTNodeLiteral(shiftRight(left, right)); + case Token::Operator::BitAnd: + return new ASTNodeLiteral(bitAnd(left, right)); + case Token::Operator::BitXor: + return new ASTNodeLiteral(bitXor(left, right)); + case Token::Operator::BitOr: + return new ASTNodeLiteral(bitOr(left, right)); + case Token::Operator::BitNot: + return new ASTNodeLiteral(bitNot(left, right)); + case Token::Operator::BoolEquals: + return new ASTNodeLiteral(bool(left == right)); + case Token::Operator::BoolNotEquals: + return new ASTNodeLiteral(bool(left != right)); + case Token::Operator::BoolGreaterThan: + return new ASTNodeLiteral(bool(left > right)); + case Token::Operator::BoolLessThan: + return new ASTNodeLiteral(bool(left < right)); + case Token::Operator::BoolGreaterThanOrEquals: + return new ASTNodeLiteral(bool(left >= right)); + case Token::Operator::BoolLessThanOrEquals: + return new ASTNodeLiteral(bool(left <= right)); + case Token::Operator::BoolAnd: + return new ASTNodeLiteral(bool(left && right)); + case Token::Operator::BoolXor: + return new ASTNodeLiteral(bool(left && !right || !left && right)); + case Token::Operator::BoolOr: + return new ASTNodeLiteral(bool(left || right)); + case Token::Operator::BoolNot: + return new ASTNodeLiteral(bool(!right)); + default: + LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); + } } - } }, left->getValue(), right->getValue()); } @@ -345,14 +345,14 @@ namespace hex::pl { ON_SCOPE_EXIT { delete first; delete second; delete third; }; auto condition = std::visit(overloaded { - [this](std::string value) -> bool { return !value.empty(); }, - [this](PatternData * const &) -> bool { LogConsole::abortEvaluation("cannot cast custom type to bool", this); }, - [](auto &&value) -> bool { return bool(value); } + [this](std::string value) -> bool { return !value.empty(); }, + [this](PatternData * const &) -> bool { LogConsole::abortEvaluation("cannot cast custom type to bool", this); }, + [](auto &&value) -> bool { return bool(value); } }, first->getValue()); return std::visit(overloaded { - [condition](const T &second, const T &third) -> ASTNode* { return new ASTNodeLiteral(condition ? second : third); }, - [this](auto &&second, auto &&third) -> ASTNode* { LogConsole::abortEvaluation("operands to ternary expression have different types", this); } + [condition](const T &second, const T &third) -> ASTNode* { return new ASTNodeLiteral(condition ? second : third); }, + [this](auto &&second, auto &&third) -> ASTNode* { LogConsole::abortEvaluation("operands to ternary expression have different types", this); } }, second->getValue(), third->getValue()); } @@ -491,9 +491,9 @@ namespace hex::pl { auto typePattern = this->m_type->createPatterns(evaluator).front(); ON_SCOPE_EXIT { - evaluator->dataOffset() = startOffset; - delete typePattern; - }; + evaluator->dataOffset() = startOffset; + delete typePattern; + }; return std::visit(overloaded { [&, this](PatternData * value) -> ASTNode* { LogConsole::abortEvaluation(hex::format("cannot cast custom type '{}' to '{}'", value->getTypeName(), Token::getTypeName(type)), this); }, @@ -601,14 +601,14 @@ namespace hex::pl { auto variables = *evaluator->getScope(0).scope; u32 startVariableCount = variables.size(); ON_SCOPE_EXIT { - s64 stackSize = evaluator->getStack().size(); - for (u32 i = startVariableCount; i < variables.size(); i++) { - stackSize--; - delete variables[i]; - } - if (stackSize < 0) LogConsole::abortEvaluation("stack pointer underflow!", this); - evaluator->getStack().resize(stackSize); - }; + s64 stackSize = evaluator->getStack().size(); + for (u32 i = startVariableCount; i < variables.size(); i++) { + stackSize--; + delete variables[i]; + } + if (stackSize < 0) LogConsole::abortEvaluation("stack pointer underflow!", this); + evaluator->getStack().resize(stackSize); + }; evaluator->pushScope(nullptr, variables); ON_SCOPE_EXIT { evaluator->popScope(); }; @@ -783,9 +783,9 @@ namespace hex::pl { ON_SCOPE_EXIT { delete offset; }; evaluator->dataOffset() = std::visit(overloaded { - [this](std::string) -> u64 { LogConsole::abortEvaluation("placement offset cannot be a string", this); }, - [this](PatternData * const &) -> u64 { LogConsole::abortEvaluation("placement offset cannot be a custom type", this); }, - [](auto &&offset) -> u64 { return offset; } + [this](std::string) -> u64 { LogConsole::abortEvaluation("placement offset cannot be a string", this); }, + [this](PatternData * const &) -> u64 { LogConsole::abortEvaluation("placement offset cannot be a custom type", this); }, + [](auto &&offset) -> u64 { return offset; } }, offset->getValue()); } @@ -976,21 +976,25 @@ namespace hex::pl { size_t size = 0; u64 entryIndex = 0; - auto addEntry = [&](PatternData *pattern) { - pattern->setVariableName(hex::format("[{}]", entryIndex)); - pattern->setEndian(arrayPattern->getEndian()); - entries.push_back(pattern); + auto addEntries = [&](const std::vector &patterns) { + for (auto pattern : patterns) { + pattern->setVariableName(hex::format("[{}]", entryIndex)); + pattern->setEndian(arrayPattern->getEndian()); + entries.push_back(pattern); - size += pattern->getSize(); - entryIndex++; + size += pattern->getSize(); + entryIndex++; - evaluator->handleAbort(); + evaluator->handleAbort(); + } }; - auto discardEntry = [&] { - delete entries.back(); - entries.pop_back(); - entryIndex--; + auto discardEntries = [&](u32 count) { + for (u32 i = 0; i < count; i++) { + delete entries.back(); + entries.pop_back(); + entryIndex--; + } }; if (this->m_size != nullptr) { @@ -1014,13 +1018,14 @@ namespace hex::pl { auto patterns = this->m_type->createPatterns(evaluator); if (!patterns.empty()) - addEntry(patterns.front()); + addEntries(patterns); auto ctrlFlow = evaluator->getCurrentControlFlowStatement(); if (ctrlFlow == ControlFlowStatement::Break) break; else if (ctrlFlow == ControlFlowStatement::Continue) { - discardEntry(); + + discardEntries(patterns.size()); continue; } } @@ -1035,19 +1040,20 @@ namespace hex::pl { auto patterns = this->m_type->createPatterns(evaluator); if (!patterns.empty()) - addEntry(patterns.front()); + addEntries(patterns); auto ctrlFlow = evaluator->getCurrentControlFlowStatement(); if (ctrlFlow == ControlFlowStatement::Break) break; else if (ctrlFlow == ControlFlowStatement::Continue) { - discardEntry(); + discardEntries(patterns.size()); continue; } } } } else { while (true) { + bool reachedEnd = true; auto limit = evaluator->getArrayLimit(); if (entryIndex > limit) LogConsole::abortEvaluation(hex::format("array grew past set limit of {}", limit), this); @@ -1056,9 +1062,7 @@ namespace hex::pl { auto patterns = this->m_type->createPatterns(evaluator); - if (!patterns.empty()) { - auto pattern = patterns.front(); - + for (auto pattern : patterns) { std::vector buffer(pattern->getSize()); if (evaluator->dataOffset() >= evaluator->getProvider()->getActualSize() - buffer.size()) { @@ -1066,18 +1070,14 @@ namespace hex::pl { LogConsole::abortEvaluation("reached end of file before finding end of unsized array", this); } - addEntry(pattern); + addEntries({ pattern }); auto ctrlFlow = evaluator->getCurrentControlFlowStatement(); - if (ctrlFlow == ControlFlowStatement::Break) + if (ctrlFlow == ControlFlowStatement::None) break; - else if (ctrlFlow == ControlFlowStatement::Continue) { - discardEntry(); - continue; - } evaluator->getProvider()->read(evaluator->dataOffset() - pattern->getSize(), buffer.data(), buffer.size()); - bool reachedEnd = true; + reachedEnd = true; for (u8 &byte : buffer) { if (byte != 0x00) { reachedEnd = false; @@ -1087,6 +1087,16 @@ namespace hex::pl { if (reachedEnd) break; } + + auto ctrlFlow = evaluator->getCurrentControlFlowStatement(); + if (ctrlFlow == ControlFlowStatement::Break) + break; + else if (ctrlFlow == ControlFlowStatement::Continue) { + discardEntries(1); + continue; + } + + if (reachedEnd) break; } } @@ -1270,8 +1280,8 @@ namespace hex::pl { for (auto inheritance : this->m_inheritance) { auto inheritancePatterns = inheritance->createPatterns(evaluator).front(); ON_SCOPE_EXIT { - delete inheritancePatterns; - }; + delete inheritancePatterns; + }; if (auto structPattern = dynamic_cast(inheritancePatterns)) { for (auto member : structPattern->getMembers()) { @@ -1669,27 +1679,27 @@ namespace hex::pl { ON_SCOPE_EXIT { delete index; }; std::visit(overloaded { - [](std::string) { throw std::string("cannot use string to index array"); }, - [](PatternData * const &) { throw std::string("cannot use custom type to index array"); }, - [&, this](auto &&index) { - if (auto dynamicArrayPattern = dynamic_cast(currPattern)) { - if (index >= searchScope.size() || index < 0) - LogConsole::abortEvaluation("array index out of bounds", this); + [](std::string) { throw std::string("cannot use string to index array"); }, + [](PatternData * const &) { throw std::string("cannot use custom type to index array"); }, + [&, this](auto &&index) { + if (auto dynamicArrayPattern = dynamic_cast(currPattern)) { + if (index >= searchScope.size() || index < 0) + LogConsole::abortEvaluation("array index out of bounds", this); - auto newPattern = searchScope[index]->clone(); - delete currPattern; - currPattern = newPattern; - } - else if (auto staticArrayPattern = dynamic_cast(currPattern)) { - if (index >= staticArrayPattern->getEntryCount() || index < 0) - LogConsole::abortEvaluation("array index out of bounds", this); + auto newPattern = searchScope[index]->clone(); + delete currPattern; + currPattern = newPattern; + } + else if (auto staticArrayPattern = dynamic_cast(currPattern)) { + if (index >= staticArrayPattern->getEntryCount() || index < 0) + LogConsole::abortEvaluation("array index out of bounds", this); - auto newPattern = searchScope.front()->clone(); - newPattern->setOffset(staticArrayPattern->getOffset() + index * staticArrayPattern->getTemplate()->getSize()); - delete currPattern; - currPattern = newPattern; + auto newPattern = searchScope.front()->clone(); + newPattern->setOffset(staticArrayPattern->getOffset() + index * staticArrayPattern->getTemplate()->getSize()); + delete currPattern; + currPattern = newPattern; + } } - } }, index->getValue()); } @@ -1805,7 +1815,7 @@ namespace hex::pl { class ASTNodeConditionalStatement : public ASTNode { public: explicit ASTNodeConditionalStatement(ASTNode *condition, std::vector trueBody, std::vector falseBody) - : ASTNode(), m_condition(condition), m_trueBody(std::move(trueBody)), m_falseBody(std::move(falseBody)) { } + : ASTNode(), m_condition(condition), m_trueBody(std::move(trueBody)), m_falseBody(std::move(falseBody)) { } ~ASTNodeConditionalStatement() override { delete this->m_condition; @@ -1835,8 +1845,9 @@ namespace hex::pl { for (auto &node : body) { auto newPatterns = node->createPatterns(evaluator); - for (auto &pattern : newPatterns) - scope.push_back(pattern->clone()); + for (auto &pattern : newPatterns) { + scope.push_back(pattern); + } } return { }; @@ -1860,14 +1871,14 @@ namespace hex::pl { auto variables = *evaluator->getScope(0).scope; u32 startVariableCount = variables.size(); ON_SCOPE_EXIT { - s64 stackSize = evaluator->getStack().size(); - for (u32 i = startVariableCount; i < variables.size(); i++) { - stackSize--; - delete variables[i]; - } - if (stackSize < 0) LogConsole::abortEvaluation("stack pointer underflow!", this); - evaluator->getStack().resize(stackSize); - }; + s64 stackSize = evaluator->getStack().size(); + for (u32 i = startVariableCount; i < variables.size(); i++) { + stackSize--; + delete variables[i]; + } + if (stackSize < 0) LogConsole::abortEvaluation("stack pointer underflow!", this); + evaluator->getStack().resize(stackSize); + }; evaluator->pushScope(nullptr, variables); ON_SCOPE_EXIT { evaluator->popScope(); }; @@ -1888,10 +1899,10 @@ namespace hex::pl { ON_SCOPE_EXIT { delete literal; }; return std::visit(overloaded { - [](std::string value) -> bool { return !value.empty(); }, - [this](PatternData * const &) -> bool { LogConsole::abortEvaluation("cannot cast custom type to bool", this); }, - [](auto &&value) -> bool { return value != 0; } - }, literal->getValue()); + [](std::string value) -> bool { return !value.empty(); }, + [this](PatternData * const &) -> bool { LogConsole::abortEvaluation("cannot cast custom type to bool", this); }, + [](auto &&value) -> bool { return value != 0; } + }, literal->getValue()); } ASTNode *m_condition; @@ -2159,7 +2170,7 @@ namespace hex::pl { class ASTNodeFunctionDefinition : public ASTNode { public: ASTNodeFunctionDefinition(std::string name, std::vector> params, std::vector body) - : m_name(std::move(name)), m_params(std::move(params)), m_body(std::move(body)) { + : m_name(std::move(name)), m_params(std::move(params)), m_body(std::move(body)) { } @@ -2206,11 +2217,11 @@ namespace hex::pl { ctx->pushScope(nullptr, variables); ON_SCOPE_EXIT { - for (auto variable : variables) - delete variable; + for (auto variable : variables) + delete variable; - ctx->popScope(); - }; + ctx->popScope(); + }; u32 paramIndex = 0; for (const auto &[name, type] : this->m_params) { diff --git a/lib/libimhex/source/pattern_language/evaluator.cpp b/lib/libimhex/source/pattern_language/evaluator.cpp index 1a2008f91..770838d94 100644 --- a/lib/libimhex/source/pattern_language/evaluator.cpp +++ b/lib/libimhex/source/pattern_language/evaluator.cpp @@ -175,7 +175,7 @@ namespace hex::pl { } } else { auto newPatterns = node->createPatterns(this); - patterns.insert(patterns.end(), newPatterns.begin(), newPatterns.end()); + std::copy(newPatterns.begin(), newPatterns.end(), std::back_inserter(patterns)); } } diff --git a/lib/libimhex/source/pattern_language/parser.cpp b/lib/libimhex/source/pattern_language/parser.cpp index 472fe736c..31fcd3394 100644 --- a/lib/libimhex/source/pattern_language/parser.cpp +++ b/lib/libimhex/source/pattern_language/parser.cpp @@ -1051,7 +1051,7 @@ namespace hex::pl { outVariable = true; } - return create(new ASTNodeVariableDecl(name, type, placementOffset, inVariable, outVariable)); + return create(new ASTNodeVariableDecl(name, type->clone(), placementOffset, inVariable, outVariable)); } // (parseType) Identifier[[(parseMathematicalExpression)]] @ Integer @@ -1078,7 +1078,7 @@ namespace hex::pl { sizeCleanup.release(); - return create(new ASTNodeArrayVariableDecl(name, type, size, placementOffset)); + return create(new ASTNodeArrayVariableDecl(name, type->clone(), size, placementOffset)); } // (parseType) *Identifier : (parseType) @ Integer @@ -1102,7 +1102,7 @@ namespace hex::pl { sizeCleanup.release(); - return create(new ASTNodePointerVariableDecl(name, type, sizeType, placementOffset)); + return create(new ASTNodePointerVariableDecl(name, type->clone(), sizeType, placementOffset)); } std::vector Parser::parseNamespace() { @@ -1137,6 +1137,7 @@ namespace hex::pl { ASTNode* Parser::parsePlacement() { auto type = parseType(); + ON_SCOPE_EXIT { delete type; }; if (MATCHES(sequence(IDENTIFIER, SEPARATOR_SQUAREBRACKETOPEN))) return parseArrayVariablePlacement(type); @@ -1151,7 +1152,10 @@ namespace hex::pl { // <(parseUsingDeclaration)|(parseVariablePlacement)|(parseStruct)> std::vector Parser::parseStatements() { - ASTNode *statement; + ASTNode *statement = nullptr; + auto statementGuard = SCOPE_GUARD { + delete statement; + }; if (MATCHES(sequence(KEYWORD_USING, IDENTIFIER))) statement = parseUsingDeclaration(); @@ -1194,6 +1198,8 @@ namespace hex::pl { // Consume superfluous semicolons while (MATCHES(sequence(SEPARATOR_ENDOFEXPRESSION))); + statementGuard.release(); + return { statement }; }