patterns: Limit max number of patterns

Can be overriden with the pattern_limit pragma
Further improves situation with #313
This commit is contained in:
WerWolv
2021-10-02 15:22:38 +02:00
parent aef959854f
commit 12a8cadcfe
7 changed files with 204 additions and 75 deletions

View File

@@ -310,21 +310,21 @@ namespace hex::pl {
PatternData *pattern;
if (Token::isUnsigned(this->m_type))
pattern = new PatternDataUnsigned(offset, size);
pattern = new PatternDataUnsigned(offset, size, evaluator);
else if (Token::isSigned(this->m_type))
pattern = new PatternDataSigned(offset, size);
pattern = new PatternDataSigned(offset, size, evaluator);
else if (Token::isFloatingPoint(this->m_type))
pattern = new PatternDataFloat(offset, size);
pattern = new PatternDataFloat(offset, size, evaluator);
else if (this->m_type == Token::ValueType::Boolean)
pattern = new PatternDataBoolean(offset);
pattern = new PatternDataBoolean(offset, evaluator);
else if (this->m_type == Token::ValueType::Character)
pattern = new PatternDataCharacter(offset);
pattern = new PatternDataCharacter(offset, evaluator);
else if (this->m_type == Token::ValueType::Character16)
pattern = new PatternDataCharacter16(offset);
pattern = new PatternDataCharacter16(offset, evaluator);
else if (this->m_type == Token::ValueType::Padding)
pattern = new PatternDataPadding(offset, 1);
pattern = new PatternDataPadding(offset, 1, evaluator);
else if (this->m_type == Token::ValueType::String)
pattern = new PatternDataString(offset, 1);
pattern = new PatternDataString(offset, 1, evaluator);
else if (this->m_type == Token::ValueType::Auto)
return { nullptr };
else
@@ -589,7 +589,6 @@ namespace hex::pl {
if (function.parameterCount != 1)
LogConsole::abortEvaluation("formatter function needs exactly one parameter", node);
pattern->setEvaluator(evaluator);
pattern->setFormatterFunction(function);
} else if (name == "transform" && requiresValue()) {
auto functions = evaluator->getCustomFunctions();
@@ -600,7 +599,6 @@ namespace hex::pl {
if (function.parameterCount != 1)
LogConsole::abortEvaluation("transform function needs exactly one parameter", node);
pattern->setEvaluator(evaluator);
pattern->setTransformFunction(function);
} else if (name == "pointer_base" && requiresValue()) {
auto functions = evaluator->getCustomFunctions();
@@ -816,13 +814,13 @@ namespace hex::pl {
PatternData *outputPattern;
if (dynamic_cast<PatternDataPadding*>(templatePattern)) {
outputPattern = new PatternDataPadding(startOffset, 0);
outputPattern = new PatternDataPadding(startOffset, 0, evaluator);
} else if (dynamic_cast<PatternDataCharacter*>(templatePattern)) {
outputPattern = new PatternDataString(startOffset, 0);
outputPattern = new PatternDataString(startOffset, 0, evaluator);
} else if (dynamic_cast<PatternDataCharacter16*>(templatePattern)) {
outputPattern = new PatternDataString16(startOffset, 0);
outputPattern = new PatternDataString16(startOffset, 0, evaluator);
} else {
auto arrayPattern = new PatternDataStaticArray(startOffset, 0);
auto arrayPattern = new PatternDataStaticArray(startOffset, 0, evaluator);
arrayPattern->setEntries(templatePattern->clone(), entryCount);
outputPattern = arrayPattern;
}
@@ -839,10 +837,15 @@ namespace hex::pl {
}
PatternData* createDynamicArray(Evaluator *evaluator) const {
auto arrayPattern = new PatternDataDynamicArray(evaluator->dataOffset(), 0);
auto arrayPattern = new PatternDataDynamicArray(evaluator->dataOffset(), 0, evaluator);
arrayPattern->setVariableName(this->m_name);
std::vector<PatternData *> entries;
auto arrayCleanup = SCOPE_GUARD {
for (auto entry : entries)
delete entry;
};
size_t size = 0;
u64 entryCount = 0;
@@ -934,6 +937,8 @@ namespace hex::pl {
arrayPattern->setEntries(entries);
arrayPattern->setSize(size);
arrayCleanup.release();
return arrayPattern;
}
};
@@ -986,7 +991,7 @@ namespace hex::pl {
auto sizePattern = this->m_sizeType->createPatterns(evaluator).front();
ON_SCOPE_EXIT { delete sizePattern; };
auto pattern = new PatternDataPointer(offset, sizePattern->getSize());
auto pattern = new PatternDataPointer(offset, sizePattern->getSize(), evaluator);
pattern->setVariableName(this->m_name);
offset = evaluator->dataOffset();
@@ -1085,10 +1090,15 @@ namespace hex::pl {
}
[[nodiscard]] std::vector<PatternData*> createPatterns(Evaluator *evaluator) const override {
auto pattern = new PatternDataStruct(evaluator->dataOffset(), 0);
auto pattern = new PatternDataStruct(evaluator->dataOffset(), 0, evaluator);
u64 startOffset = evaluator->dataOffset();
std::vector<PatternData*> memberPatterns;
auto structCleanup = SCOPE_GUARD {
delete pattern;
for (auto member : memberPatterns)
delete member;
};
evaluator->pushScope(pattern, memberPatterns);
@@ -1116,6 +1126,8 @@ namespace hex::pl {
pattern->setMembers(memberPatterns);
pattern->setSize(evaluator->dataOffset() - startOffset);
structCleanup.release();
return { pattern };
}
@@ -1149,12 +1161,18 @@ namespace hex::pl {
}
[[nodiscard]] std::vector<PatternData*> createPatterns(Evaluator *evaluator) const override {
auto pattern = new PatternDataUnion(evaluator->dataOffset(), 0);
auto pattern = new PatternDataUnion(evaluator->dataOffset(), 0, evaluator);
size_t size = 0;
std::vector<PatternData*> memberPatterns;
u64 startOffset = evaluator->dataOffset();
auto unionCleanup = SCOPE_GUARD {
delete pattern;
for (auto member : memberPatterns)
delete member;
};
evaluator->pushScope(pattern, memberPatterns);
for (auto member : this->m_members) {
for (auto &memberPattern : member->createPatterns(evaluator)) {
@@ -1169,6 +1187,8 @@ namespace hex::pl {
pattern->setMembers(memberPatterns);
pattern->setSize(size);
unionCleanup.release();
return { pattern };
}
@@ -1200,7 +1220,9 @@ namespace hex::pl {
}
[[nodiscard]] std::vector<PatternData*> createPatterns(Evaluator *evaluator) const override {
auto pattern = new PatternDataEnum(evaluator->dataOffset(), 0);
auto pattern = new PatternDataEnum(evaluator->dataOffset(), 0, evaluator);
auto enumCleanup = SCOPE_GUARD { delete pattern; };
std::vector<std::pair<Token::Literal, std::string>> enumEntries;
for (const auto &[name, value] : this->m_entries) {
@@ -1217,6 +1239,8 @@ namespace hex::pl {
pattern->setSize(underlying->getSize());
pattern->setEndian(underlying->getEndian());
enumCleanup.release();
return { pattern };
}
@@ -1252,10 +1276,17 @@ namespace hex::pl {
void addEntry(const std::string &name, ASTNode* size) { this->m_entries.emplace_back(name, size); }
[[nodiscard]] std::vector<PatternData*> createPatterns(Evaluator *evaluator) const override {
auto pattern = new PatternDataBitfield(evaluator->dataOffset(), 0);
auto pattern = new PatternDataBitfield(evaluator->dataOffset(), 0, evaluator);
size_t bitOffset = 0;
std::vector<PatternData*> fields;
auto bitfieldCleanup = SCOPE_GUARD {
delete pattern;
for (auto field : fields)
delete field;
};
evaluator->pushScope(pattern, fields);
for (auto [name, bitSizeNode] : this->m_entries) {
auto literal = bitSizeNode->evaluate(evaluator);
@@ -1267,7 +1298,7 @@ namespace hex::pl {
[](auto &&offset) -> u8 { return static_cast<u8>(offset); }
}, dynamic_cast<ASTNodeLiteral*>(literal)->getValue());
auto field = new PatternDataBitfieldField(evaluator->dataOffset(), bitOffset, bitSize);
auto field = new PatternDataBitfieldField(evaluator->dataOffset(), bitOffset, bitSize, evaluator);
field->setVariableName(name);
bitOffset += bitSize;
@@ -1280,6 +1311,8 @@ namespace hex::pl {
evaluator->dataOffset() += pattern->getSize();
bitfieldCleanup.release();
return { pattern };
}
@@ -1915,7 +1948,12 @@ namespace hex::pl {
std::vector<PatternData*> variables;
ctx->pushScope(nullptr, variables);
ON_SCOPE_EXIT { ctx->popScope(); };
ON_SCOPE_EXIT {
for (auto variable : variables)
delete variable;
ctx->popScope();
};
u32 paramIndex = 0;
for (const auto &[name, type] : this->m_params) {

View File

@@ -15,6 +15,7 @@ namespace hex::prv { class Provider; }
namespace hex::pl {
class PatternData;
class PatternCreationLimiter;
class ASTNode;
class Evaluator {
@@ -87,6 +88,20 @@ namespace hex::pl {
return this->m_arrayLimit;
}
void setPatternLimit(u32 limit) {
this->m_patternLimit = limit;
}
[[nodiscard]]
u32 getPatternLimit() {
return this->m_patternLimit;
}
[[nodiscard]]
u32 getPatternCount() {
return this->m_currPatternCount;
}
u64& dataOffset() { return this->m_currOffset; }
bool addCustomFunction(const std::string &name, u32 numParams, const ContentRegistry::PatternLanguageFunctions::Callback &function) {
@@ -106,9 +121,13 @@ 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);
private:
void patternCreated();
void patternDestroyed();
private:
u64 m_currOffset;
prv::Provider *m_provider = nullptr;
@@ -117,11 +136,16 @@ namespace hex::pl {
std::endian m_defaultEndian = std::endian::native;
u32 m_evalDepth;
u32 m_arrayLimit;
u32 m_patternLimit;
u32 m_currPatternCount;
std::vector<Scope> m_scopes;
std::map<std::string, ContentRegistry::PatternLanguageFunctions::Function> m_customFunctions;
std::vector<ASTNode*> m_customFunctionDefinitions;
std::vector<Token::Literal> m_stack;
friend class PatternCreationLimiter;
};
}

View File

@@ -6,6 +6,8 @@
#include <hex/providers/provider.hpp>
#include <hex/pattern_language/token.hpp>
#include <hex/pattern_language/evaluator.hpp>
#include <hex/views/view.hpp>
#include <hex/helpers/utils.hpp>
#include <hex/helpers/fmt.hpp>
@@ -51,10 +53,29 @@ namespace hex::pl {
bool m_inlined = false;
};
class PatternData {
class PatternCreationLimiter {
public:
PatternData(u64 offset, size_t size, u32 color = 0)
: m_offset(offset), m_size(size), m_color(color), m_parent(nullptr) {
explicit PatternCreationLimiter(Evaluator *evaluator) : m_evaluator(evaluator) {
this->m_evaluator->patternCreated();
}
PatternCreationLimiter(const PatternCreationLimiter &other) {
this->m_evaluator = other.m_evaluator;
this->m_evaluator->patternCreated();
}
~PatternCreationLimiter() {
this->m_evaluator->patternDestroyed();
}
private:
Evaluator *m_evaluator;
};
class PatternData : public PatternCreationLimiter {
public:
PatternData(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0)
: PatternCreationLimiter(evaluator), m_offset(offset), m_size(size), m_color(color), m_parent(nullptr), m_evaluator(evaluator) {
constexpr u32 Palette[] = { 0x70b4771f, 0x700e7fff, 0x702ca02c, 0x702827d6, 0x70bd6794, 0x704b568c, 0x70c277e3, 0x707f7f7f, 0x7022bdbc, 0x70cfbe17 };
if (color != 0)
@@ -100,7 +121,6 @@ namespace hex::pl {
void setDisplayName(const std::string &name) { this->m_displayName = name; }
[[nodiscard]] Evaluator* getEvaluator() const { return this->m_evaluator; }
void setEvaluator(Evaluator *evaluator) { this->m_evaluator = evaluator; }
[[nodiscard]] const auto& getTransformFunction() const { return this->m_transformFunction; }
void setTransformFunction(const ContentRegistry::PatternLanguageFunctions::Function &function) { this->m_transformFunction = function; }
@@ -295,7 +315,7 @@ namespace hex::pl {
class PatternDataPadding : public PatternData {
public:
PatternDataPadding(u64 offset, size_t size) : PatternData(offset, size, 0xFF000000) { }
PatternDataPadding(u64 offset, size_t size, Evaluator *evaluator) : PatternData(offset, size, evaluator, 0xFF000000) { }
PatternData* clone() override {
return new PatternDataPadding(*this);
@@ -313,8 +333,8 @@ namespace hex::pl {
class PatternDataPointer : public PatternData {
public:
PatternDataPointer(u64 offset, size_t size, u32 color = 0)
: PatternData(offset, size, color), m_pointedAt(nullptr) {
PatternDataPointer(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0)
: PatternData(offset, size, evaluator, color), m_pointedAt(nullptr) {
}
PatternDataPointer(const PatternDataPointer &other) : PatternData(other) {
@@ -415,8 +435,8 @@ namespace hex::pl {
class PatternDataUnsigned : public PatternData {
public:
PatternDataUnsigned(u64 offset, size_t size, u32 color = 0)
: PatternData(offset, size, color) { }
PatternDataUnsigned(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0)
: PatternData(offset, size, evaluator, color) { }
PatternData* clone() override {
return new PatternDataUnsigned(*this);
@@ -446,8 +466,8 @@ namespace hex::pl {
class PatternDataSigned : public PatternData {
public:
PatternDataSigned(u64 offset, size_t size, u32 color = 0)
: PatternData(offset, size, color) { }
PatternDataSigned(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0)
: PatternData(offset, size, evaluator, color) { }
PatternData* clone() override {
return new PatternDataSigned(*this);
@@ -478,8 +498,8 @@ namespace hex::pl {
class PatternDataFloat : public PatternData {
public:
PatternDataFloat(u64 offset, size_t size, u32 color = 0)
: PatternData(offset, size, color) { }
PatternDataFloat(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0)
: PatternData(offset, size, evaluator, color) { }
PatternData* clone() override {
return new PatternDataFloat(*this);
@@ -514,8 +534,8 @@ namespace hex::pl {
class PatternDataBoolean : public PatternData {
public:
explicit PatternDataBoolean(u64 offset, u32 color = 0)
: PatternData(offset, 1, color) { }
explicit PatternDataBoolean(u64 offset, Evaluator *evaluator, u32 color = 0)
: PatternData(offset, 1, evaluator, color) { }
PatternData* clone() override {
return new PatternDataBoolean(*this);
@@ -542,8 +562,8 @@ namespace hex::pl {
class PatternDataCharacter : public PatternData {
public:
explicit PatternDataCharacter(u64 offset, u32 color = 0)
: PatternData(offset, 1, color) { }
explicit PatternDataCharacter(u64 offset, Evaluator *evaluator, u32 color = 0)
: PatternData(offset, 1, evaluator, color) { }
PatternData* clone() override {
return new PatternDataCharacter(*this);
@@ -565,8 +585,8 @@ namespace hex::pl {
class PatternDataCharacter16 : public PatternData {
public:
explicit PatternDataCharacter16(u64 offset, u32 color = 0)
: PatternData(offset, 2, color) { }
explicit PatternDataCharacter16(u64 offset, Evaluator *evaluator, u32 color = 0)
: PatternData(offset, 2, evaluator, color) { }
PatternData* clone() override {
return new PatternDataCharacter16(*this);
@@ -590,8 +610,8 @@ namespace hex::pl {
class PatternDataString : public PatternData {
public:
PatternDataString(u64 offset, size_t size, u32 color = 0)
: PatternData(offset, size, color) { }
PatternDataString(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0)
: PatternData(offset, size, evaluator, color) { }
PatternData* clone() override {
return new PatternDataString(*this);
@@ -613,8 +633,8 @@ namespace hex::pl {
class PatternDataString16 : public PatternData {
public:
PatternDataString16(u64 offset, size_t size, u32 color = 0)
: PatternData(offset, size, color) { }
PatternDataString16(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0)
: PatternData(offset, size, evaluator, color) { }
PatternData* clone() override {
return new PatternDataString16(*this);
@@ -641,8 +661,8 @@ namespace hex::pl {
class PatternDataDynamicArray : public PatternData, public Inlinable {
public:
PatternDataDynamicArray(u64 offset, size_t size, u32 color = 0)
: PatternData(offset, size, color) {
PatternDataDynamicArray(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0)
: PatternData(offset, size, evaluator, color) {
}
PatternDataDynamicArray(const PatternDataDynamicArray &other) : PatternData(other) {
@@ -773,8 +793,8 @@ namespace hex::pl {
class PatternDataStaticArray : public PatternData, public Inlinable {
public:
PatternDataStaticArray(u64 offset, size_t size, u32 color = 0)
: PatternData(offset, size, color) {
PatternDataStaticArray(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0)
: PatternData(offset, size, evaluator, color) {
}
PatternDataStaticArray(const PatternDataStaticArray &other) : PatternData(other) {
@@ -910,7 +930,8 @@ namespace hex::pl {
class PatternDataStruct : public PatternData, public Inlinable {
public:
PatternDataStruct(u64 offset, size_t size, u32 color = 0) : PatternData(offset, size, color){
PatternDataStruct(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0)
: PatternData(offset, size, evaluator, color){
}
PatternDataStruct(const PatternDataStruct &other) : PatternData(other) {
@@ -1045,7 +1066,8 @@ namespace hex::pl {
class PatternDataUnion : public PatternData, public Inlinable {
public:
PatternDataUnion(u64 offset, size_t size, u32 color = 0) : PatternData(offset, size, color) {
PatternDataUnion(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0)
: PatternData(offset, size, evaluator, color) {
}
@@ -1181,7 +1203,8 @@ namespace hex::pl {
class PatternDataEnum : public PatternData {
public:
PatternDataEnum(u64 offset, size_t size, u32 color = 0) : PatternData(offset, size, color) {
PatternDataEnum(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0)
: PatternData(offset, size, evaluator, color) {
}
@@ -1274,8 +1297,8 @@ namespace hex::pl {
class PatternDataBitfieldField : public PatternData {
public:
PatternDataBitfieldField(u64 offset, u8 bitOffset, u8 bitSize, u32 color = 0)
: m_bitOffset(bitOffset), m_bitSize(bitSize), PatternData(offset, 0, color) {
PatternDataBitfieldField(u64 offset, u8 bitOffset, u8 bitSize, Evaluator *evaluator, u32 color = 0)
: m_bitOffset(bitOffset), m_bitSize(bitSize), PatternData(offset, 0, evaluator, color) {
}
@@ -1343,7 +1366,8 @@ namespace hex::pl {
class PatternDataBitfield : public PatternData, public Inlinable {
public:
PatternDataBitfield(u64 offset, size_t size, u32 color = 0) : PatternData(offset, size, color) {
PatternDataBitfield(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0)
: PatternData(offset, size, evaluator, color) {
}

View File

@@ -34,6 +34,9 @@ namespace hex::pl {
const std::vector<std::pair<LogConsole::Level, std::string>>& getConsoleLog();
const std::optional<std::pair<u32, std::string>>& getError();
u32 getCreatedPatternCount();
u32 getMaximumPatternCount();
private:
Preprocessor *m_preprocessor;
Lexer *m_lexer;
@@ -45,8 +48,6 @@ namespace hex::pl {
prv::Provider *m_provider = nullptr;
std::endian m_defaultEndian = std::endian::native;
u32 m_evalDepth;
u32 m_arrayLimit;
std::optional<std::pair<u32, std::string>> m_currError;
};