Skip to content

Commit

Permalink
Fix segfault when nested rules change their context (fixes #145, fixes
Browse files Browse the repository at this point in the history
…#146, fixes #148)
  • Loading branch information
TinoDidriksen committed Aug 10, 2024
1 parent 0dbbe61 commit 9f09633
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 3 deletions.
2 changes: 2 additions & 0 deletions src/GrammarApplicator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,8 @@ class GrammarApplicator {
Cohort* merge_with = nullptr;
Rule* current_rule = nullptr;
std::vector<Rule_Context> context_stack;
std::vector<CohortSet*> cohortsets;
std::vector<CohortSet::const_iterator*> rocits;

ReadingSpec get_attach_to();
Cohort* get_mark();
Expand Down
44 changes: 42 additions & 2 deletions src/GrammarApplicator_runRules.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,38 @@ bool GrammarApplicator::updateRuleToCohorts(Cohort& c, const uint32_t& rsit) {
indexSingleWindow(*current);
}
CohortSet& cohortset = current->rule_to_cohorts[rsit];
cohortset.insert(&c);
std::vector<size_t> csi;
for (size_t i = 0; i < cohortsets.size(); ++i) {
if (cohortsets[i] != &cohortset) {
continue;
}
csi.push_back(i);
}
if (!csi.empty()) {
auto cap = cohortset.capacity();
std::vector<CohortSet::const_iterator*> ends;
std::vector<std::pair<CohortSet::const_iterator*,Cohort*>> chs;
for (size_t i = 0; i < csi.size(); ++i) {
if (*rocits[csi[i]] == cohortset.end()) {
ends.push_back(rocits[csi[i]]);
}
else {
chs.push_back(std::pair(rocits[csi[i]], **rocits[csi[i]]));
}
}
cohortset.insert(&c);
for (auto it : ends) {
*it = cohortset.end();
}
if (cap != cohortset.capacity()) {
for (auto& it : chs) {
*it.first = cohortset.find(it.second);
}
}
}
else {
cohortset.insert(&c);
}
return current->valid_rules.insert(rsit);
}

Expand Down Expand Up @@ -333,11 +364,19 @@ bool GrammarApplicator::runSingleRule(SingleWindow& current, const Rule& rule, R
}
};
override_cohortset();
cohortsets.push_back(cohortset);
rocits.push_back(nullptr);

scope_guard popper([&]() {
cohortsets.pop_back();
rocits.pop_back();
});

if (debug_level > 1) {
std::cerr << "DEBUG: " << cohortset->size() << "/" << current.cohorts.size() << " = " << double(cohortset->size()) / double(current.cohorts.size()) << std::endl;
}
for (auto rocit = cohortset->cbegin(); rocit != cohortset->cend();) {
for (auto rocit = cohortset->cbegin(); (!cohortset->empty()) && (rocit != cohortset->cend());) {
rocits.back() = &rocit;
Cohort* cohort = *rocit;
++rocit;

Expand Down Expand Up @@ -483,6 +522,7 @@ bool GrammarApplicator::runSingleRule(SingleWindow& current, const Rule& rule, R
auto reset_cohorts = [&]() {
cohortset = &current.rule_to_cohorts[rule.number];
override_cohortset();
cohortsets.back() = cohortset;
if (get_apply_to().cohort->type & CT_REMOVED) {
rocit = cohortset->lower_bound(current.cohorts[get_apply_to().cohort->local_number]);
}
Expand Down
21 changes: 21 additions & 0 deletions src/inlines.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,27 @@ class inc_dec {
T* p;
};

class scope_guard {
public:
scope_guard(std::function<void()> func, bool good = true)
: func(func)
, good(good)
{}

~scope_guard() {
if (good) {
func();
}
}

void set(bool val = true) {
good = val;
}
private:
std::function<void()> func;
bool good = true;
};

template<typename T>
inline T* reverse(T* head) {
T* nr = nullptr;
Expand Down
2 changes: 1 addition & 1 deletion src/version.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ constexpr auto CG3_COPYRIGHT_STRING = "Copyright (C) 2007-2024 GrammarSoft ApS.

constexpr uint32_t CG3_VERSION_MAJOR = 1;
constexpr uint32_t CG3_VERSION_MINOR = 4;
constexpr uint32_t CG3_VERSION_PATCH = 15;
constexpr uint32_t CG3_VERSION_PATCH = 16;
constexpr uint32_t CG3_REVISION = 13898;
constexpr uint32_t CG3_FEATURE_REV = 13898;
constexpr uint32_t CG3_TOO_OLD = 10373;
Expand Down

0 comments on commit 9f09633

Please sign in to comment.