diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2014-11-19 11:13:19 +0100 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2014-11-19 11:13:19 +0100 |
commit | f9fb1fcb8e0558a719cc6b423064d19433ce5e37 (patch) | |
tree | a0d2c0f1017775a590c3372543a5043e2781577b /unoidl/source | |
parent | 6635508ad59515311245245472f7a38eabab28cd (diff) |
Guard against cyclic entity dependencies
...in unoidl-read, although it would be better (but more expensive at start-
up) to check consistency in unoidl::Manager.
Change-Id: I5f5894fcd51af3aa999fe30621f52bfd11d0e610
Diffstat (limited to 'unoidl/source')
-rw-r--r-- | unoidl/source/unoidl-read.cxx | 29 |
1 files changed, 20 insertions, 9 deletions
diff --git a/unoidl/source/unoidl-read.cxx b/unoidl/source/unoidl-read.cxx index 113acee777c0..e301ba5654c1 100644 --- a/unoidl/source/unoidl-read.cxx +++ b/unoidl/source/unoidl-read.cxx @@ -136,16 +136,19 @@ OUString decomposeType( } struct Entity { + enum class Sorted { NO, ACTIVE, YES }; + explicit Entity( rtl::Reference<unoidl::Entity> const & theEntity, bool theRelevant): - entity(theEntity), relevant(theRelevant), sorted(false), written(false) + entity(theEntity), relevant(theRelevant), sorted(Sorted::NO), + written(false) {} rtl::Reference<unoidl::Entity> const entity; std::set<OUString> dependencies; std::set<OUString> interfaceDependencies; bool relevant; - bool sorted; + Sorted sorted; bool written; }; @@ -160,7 +163,7 @@ void insertEntityDependency( if (weakInterfaceDependency) { rtl::Reference<unoidl::Entity> ent(manager->findEntity(name)); if (!ent.is()) { - std::cerr << "unknown entity " << name << std::endl; + std::cerr << "Unknown entity " << name << std::endl; std::exit(EXIT_FAILURE); } ifc = ent->getSort() == unoidl::Entity::SORT_INTERFACE_TYPE; @@ -404,7 +407,7 @@ void scanMap( void propagateRelevant(std::map<OUString, Entity> & entities, Entity & entity) { if (!entity.relevant) { entity.relevant = true; - if (entity.sorted) { + if (entity.sorted != Entity::Sorted::YES) { for (std::set<OUString>::iterator i(entity.dependencies.begin()); i != entity.dependencies.end(); ++i) { @@ -422,10 +425,9 @@ void visit( std::map<OUString, Entity>::iterator const & iterator, std::vector<OUString> & result) { - if (!iterator->second.sorted) { - // Doesn't bother to verify the graph is acyclic (which it is guaranteed - // to be for a consistent set of entities); a non-DAG will lead to - // infinite recursion/stack overflow: + switch (iterator->second.sorted) { + case Entity::Sorted::NO: + iterator->second.sorted = Entity::Sorted::ACTIVE; for (std::set<OUString>::iterator i( iterator->second.dependencies.begin()); i != iterator->second.dependencies.end(); ++i) @@ -438,8 +440,17 @@ void visit( visit(entities, j, result); } } - iterator->second.sorted = true; + iterator->second.sorted = Entity::Sorted::YES; result.push_back(iterator->first); + break; + case Entity::Sorted::ACTIVE: + std::cerr + << "Entity " << iterator->first << " recursively depends on itself" + << std::endl; + std::exit(EXIT_FAILURE); + // fall-through avoids warnings + default: + break; } } |