From 06eeea8cb2782b90113148954bba5fdd8c54b5d1 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 13 Feb 2025 12:07:00 +0100 Subject: [PATCH] PD: Fix crash in Loft::getSectionShape The passed DocumentObject pointer can be null which is nowhere checked. This fixes issue 19545 Fixes: 256ad7a01aa2 ("PartDesign: Loft Intelligence - Select the whole sketch if the selected shape is ...") --- src/Mod/PartDesign/App/FeatureLoft.cpp | 67 +++++++++++++++++--------- 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/src/Mod/PartDesign/App/FeatureLoft.cpp b/src/Mod/PartDesign/App/FeatureLoft.cpp index becc62d406..25bd92c722 100644 --- a/src/Mod/PartDesign/App/FeatureLoft.cpp +++ b/src/Mod/PartDesign/App/FeatureLoft.cpp @@ -65,32 +65,55 @@ short Loft::mustExecute() const return ProfileBased::mustExecute(); } -std::vector -Loft::getSectionShape(const char *name, - App::DocumentObject *obj, - const std::vector &subs, - size_t expected_size) +std::vector Loft::getSectionShape(const char* name, + App::DocumentObject* obj, + const std::vector& subs, + size_t expected_size) { + auto useSketch = [](App::DocumentObject* obj, const std::vector& subs) { + // Be smart. If part of a sketch is selected, use the entire sketch unless it is a single + // vertex - backward compatibility (#16630) + if (!obj) { + return false; + } + + auto subName = subs.empty() ? "" : subs.front(); + return obj->isDerivedFrom() && subName.find("Vertex") != 0; + }; + std::vector shapes; - // Be smart. If part of a sketch is selected, use the entire sketch unless it is a single vertex - - // backward compatibility (#16630) - auto subName = subs.empty() ? "" : subs.front(); - auto useEntireSketch = obj->isDerivedFrom() && subName.find("Vertex") != 0; - if (subs.empty() || std::ranges::find(subs, std::string()) != subs.end() || useEntireSketch ) { - shapes.push_back(Part::Feature::getTopoShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform)); - if (shapes.back().isNull()) - FC_THROWM(Part::NullShapeException, "Failed to get shape of " - << name << " " << App::SubObjectT(obj, "").getSubObjectFullName(obj->getDocument()->getName())); - } else { - for (const auto &sub : subs) { + auto useEntireSketch = useSketch(obj, subs); + if (subs.empty() || std::ranges::find(subs, std::string()) != subs.end() || useEntireSketch) { + shapes.push_back(Part::Feature::getTopoShape(obj, + Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform)); + if (shapes.back().isNull()) { + std::stringstream str; + str << "Failed to get shape of " << name; + if (obj) { + auto doc = obj->getDocument(); + str << " " << App::SubObjectT(obj, "").getSubObjectFullName(doc->getName()); + } + THROWM(Part::NullShapeException, str.str()); + } + } + else { + for (const auto& sub : subs) { shapes.push_back(Part::Feature::getTopoShape(obj, - Part::ShapeOption::NeedSubElement - | Part::ShapeOption::ResolveLink - | Part::ShapeOption::Transform, + Part::ShapeOption::NeedSubElement + | Part::ShapeOption::ResolveLink + | Part::ShapeOption::Transform, sub.c_str())); - if (shapes.back().isNull()) - FC_THROWM(Part::NullShapeException, "Failed to get shape of " << name << " " - << App::SubObjectT(obj, sub.c_str()).getSubObjectFullName(obj->getDocument()->getName())); + if (shapes.back().isNull()) { + std::stringstream str; + str << "Failed to get shape of " << name; + if (obj) { + auto doc = obj->getDocument(); + App::SubObjectT subObj(obj, sub.c_str()); + str << " " << subObj.getSubObjectFullName(doc->getName()); + } + THROWM(Part::NullShapeException, str.str()); + } } } auto compound = TopoShape(0).makeElementCompound(shapes, "", TopoShape::SingleShapeCompoundCreationPolicy::returnShape);