PD: Fix crash in Loft::getSectionShape

The passed DocumentObject pointer can be null which is nowhere checked.
This fixes issue 19545

Fixes: 256ad7a01a ("PartDesign: Loft Intelligence - Select the whole sketch if the selected shape is ...")
This commit is contained in:
wmayer
2025-02-13 12:07:00 +01:00
committed by Chris Hennes
parent 2a42e87c57
commit 06eeea8cb2

View File

@@ -65,32 +65,55 @@ short Loft::mustExecute() const
return ProfileBased::mustExecute();
}
std::vector<Part::TopoShape>
Loft::getSectionShape(const char *name,
App::DocumentObject *obj,
const std::vector<std::string> &subs,
size_t expected_size)
std::vector<Part::TopoShape> Loft::getSectionShape(const char* name,
App::DocumentObject* obj,
const std::vector<std::string>& subs,
size_t expected_size)
{
auto useSketch = [](App::DocumentObject* obj, const std::vector<std::string>& 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<Part::Part2DObject>() && subName.find("Vertex") != 0;
};
std::vector<TopoShape> 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<Part::Part2DObject>() && 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);