From d793a182c47077fb0aaacfddf680f47aaa741b49 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 17 Nov 2022 00:30:44 +0100 Subject: [PATCH] App: fix possible stack overflow in GroupExtension::hasObject() --- src/App/GroupExtension.cpp | 62 +++++++++++++++++++++----------------- src/App/GroupExtension.h | 4 +-- 2 files changed, 37 insertions(+), 29 deletions(-) diff --git a/src/App/GroupExtension.cpp b/src/App/GroupExtension.cpp index e3fd311331..fb9ab4b1a6 100644 --- a/src/App/GroupExtension.cpp +++ b/src/App/GroupExtension.cpp @@ -182,34 +182,41 @@ DocumentObject *GroupExtension::getObject(const char *Name) const bool GroupExtension::hasObject(const DocumentObject* obj, bool recursive) const { - - if(obj == getExtendedObject()) + if (obj == getExtendedObject()) { return false; - - const std::vector& grp = Group.getValues(); - for (auto child : grp) { - - if(!child) - continue; - - if (child == obj) { - return true; - } else if (child == getExtendedObject()) { - Base::RuntimeError("Cyclic dependencies detected: Search cannot be performed"); - } else if ( recursive && child->hasExtension(GroupExtension::getExtensionClassTypeId()) ) { - - App::GroupExtension *subGroup = static_cast ( - child->getExtension(GroupExtension::getExtensionClassTypeId())); - std::vector history; - history.push_back(this); - - if (subGroup->recursiveHasObject (obj, subGroup, history)) { - return true; - } - } } - return false; + try { + const std::vector& grp = Group.getValues(); + for (auto child : grp) { + + if (!child) + continue; + + if (child == obj) { + return true; + } + else if (child == getExtendedObject()) { + throw Base::RuntimeError("Cyclic dependencies detected: Search cannot be performed"); + } + else if ( recursive && child->hasExtension(GroupExtension::getExtensionClassTypeId()) ) { + App::GroupExtension *subGroup = static_cast ( + child->getExtension(GroupExtension::getExtensionClassTypeId())); + std::vector history; + history.push_back(this); + + if (subGroup->recursiveHasObject (obj, subGroup, history)) { + return true; + } + } + } + + return false; + } + catch (const Base::RuntimeError& e) { + e.ReportException(); + return false; + } } bool GroupExtension::recursiveHasObject(const DocumentObject* obj, const GroupExtension* group, @@ -235,8 +242,9 @@ bool GroupExtension::recursiveHasObject(const DocumentObject* obj, const GroupEx auto ext = child->getExtensionByType(); - if(std::find(history.begin(), history.end(), ext) != history.end()) - Base::RuntimeError("Cyclic dependencies detected: Search cannot be performed"); + if (std::find(history.begin(), history.end(), ext) != history.end()) { + throw Base::RuntimeError("Cyclic dependencies detected: Search cannot be performed"); + } if (recursiveHasObject(obj, ext, history)) { return true; diff --git a/src/App/GroupExtension.h b/src/App/GroupExtension.h index 189a8ea93b..65d4a583a6 100644 --- a/src/App/GroupExtension.h +++ b/src/App/GroupExtension.h @@ -127,8 +127,8 @@ public: private: void removeObjectFromDocument(DocumentObject*); - //this version if has object stores the already searched objects to prevent infinite recursion - //in case of a cyclic group graph + // This function stores the already searched objects to prevent infinite recursion in case of a cyclic group graph + // It throws an exception of type Base::RuntimeError if a cyclic dependency is detected. bool recursiveHasObject(const DocumentObject* obj, const GroupExtension* group, std::vector history) const; // for tracking children visibility