This commit is contained in:
yhirose 2022-06-16 21:34:21 -04:00
parent af43f1f18a
commit f6b1a7380d

View File

@ -1950,8 +1950,9 @@ private:
}; };
struct HasEmptyElement : public Ope::Visitor { struct HasEmptyElement : public Ope::Visitor {
HasEmptyElement(std::vector<std::pair<const char *, std::string>> &refs) HasEmptyElement(std::vector<std::pair<const char *, std::string>> &refs,
: refs_(refs) {} std::unordered_map<std::string, bool> &has_error_cache)
: refs_(refs), has_error_cache_(has_error_cache) {}
void visit(Sequence &ope) override; void visit(Sequence &ope) override;
void visit(PrioritizedChoice &ope) override { void visit(PrioritizedChoice &ope) override {
@ -1993,17 +1994,20 @@ private:
tie(error_s, error_name) = refs_.back(); tie(error_s, error_name) = refs_.back();
} }
std::vector<std::pair<const char *, std::string>> &refs_; std::vector<std::pair<const char *, std::string>> &refs_;
std::unordered_map<std::string, bool> &has_error_cache_;
}; };
struct DetectInfiniteLoop : public Ope::Visitor { struct DetectInfiniteLoop : public Ope::Visitor {
DetectInfiniteLoop(const char *s, const std::string &name, DetectInfiniteLoop(const char *s, const std::string &name,
std::vector<std::pair<const char *, std::string>> &refs) std::vector<std::pair<const char *, std::string>> &refs,
: refs_(refs) { std::unordered_map<std::string, bool> &has_error_cache)
: refs_(refs), has_error_cache_(has_error_cache) {
refs_.emplace_back(s, name); refs_.emplace_back(s, name);
} }
DetectInfiniteLoop(std::vector<std::pair<const char *, std::string>> &refs) DetectInfiniteLoop(std::vector<std::pair<const char *, std::string>> &refs,
: refs_(refs) {} std::unordered_map<std::string, bool> &has_error_cache)
: refs_(refs), has_error_cache_(has_error_cache) {}
void visit(Sequence &ope) override { void visit(Sequence &ope) override {
for (auto op : ope.opes_) { for (auto op : ope.opes_) {
@ -2019,7 +2023,7 @@ struct DetectInfiniteLoop : public Ope::Visitor {
} }
void visit(Repetition &ope) override { void visit(Repetition &ope) override {
if (ope.max_ == std::numeric_limits<size_t>::max()) { if (ope.max_ == std::numeric_limits<size_t>::max()) {
HasEmptyElement vis(refs_); HasEmptyElement vis(refs_, has_error_cache_);
ope.ope_->accept(vis); ope.ope_->accept(vis);
if (vis.is_empty) { if (vis.is_empty) {
has_error = true; has_error = true;
@ -2049,7 +2053,7 @@ struct DetectInfiniteLoop : public Ope::Visitor {
private: private:
std::vector<std::pair<const char *, std::string>> &refs_; std::vector<std::pair<const char *, std::string>> &refs_;
std::unordered_map<std::string, bool> has_error_cache_; std::unordered_map<std::string, bool> &has_error_cache_;
}; };
struct ReferenceChecker : public Ope::Visitor { struct ReferenceChecker : public Ope::Visitor {
@ -3041,7 +3045,7 @@ inline void HasEmptyElement::visit(Sequence &ope) {
if (!is_empty) { if (!is_empty) {
++it; ++it;
while (it != ope.opes_.end()) { while (it != ope.opes_.end()) {
DetectInfiniteLoop vis(refs_); DetectInfiniteLoop vis(refs_, has_error_cache_);
(*it)->accept(vis); (*it)->accept(vis);
if (vis.has_error) { if (vis.has_error) {
is_empty = true; is_empty = true;
@ -4048,7 +4052,8 @@ private:
bool detect_infiniteLoop(const Data &data, Definition &rule, const Log &log, bool detect_infiniteLoop(const Data &data, Definition &rule, const Log &log,
const char *s) const { const char *s) const {
std::vector<std::pair<const char *, std::string>> refs; std::vector<std::pair<const char *, std::string>> refs;
DetectInfiniteLoop vis(data.start_pos, rule.name, refs); std::unordered_map<std::string, bool> has_error_cache;
DetectInfiniteLoop vis(data.start_pos, rule.name, refs, has_error_cache);
rule.accept(vis); rule.accept(vis);
if (vis.has_error) { if (vis.has_error) {
if (log) { if (log) {