Skip to content

Fix segfault in Bullet Featherstone plugin when loading ball joint#868

Merged
iche033 merged 2 commits into
gazebosim:mainfrom
XINJIANGMO:fixbug-864
Feb 12, 2026
Merged

Fix segfault in Bullet Featherstone plugin when loading ball joint#868
iche033 merged 2 commits into
gazebosim:mainfrom
XINJIANGMO:fixbug-864

Conversation

@XINJIANGMO

Copy link
Copy Markdown
Contributor

🦟 Bug fix

Fixes #864

Summary

Fixed a segmentation fault in the Bullet Featherstone plugin triggered by SDF models containing ball joints.
Added a null pointer check for joint->Axis() to prevent invalid access when loading joints that lack an axis definition.

Checklist

  • Signed all commits for DCO
  • Added tests
  • Updated documentation (as needed)
  • Updated migration guide (as needed)
  • Consider updating Python bindings (if the library has them)
  • codecheck passed (See contributing)
  • All tests passed (See test coverage)

Signed-off-by: momo <2438833481@qq.com>
Copilot AI review requested due to automatic review settings February 12, 2026 16:23

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a crash in the Bullet Featherstone SDF model construction path when encountering joints without an axis definition (notably ball joints), improving robustness while loading SDF models.

Changes:

  • Added a null check around joint->Axis() before reading axis-dependent limits / damping / effort parameters.
  • Prevented axis-derived joint metadata from being populated when the axis is absent.
Comments suppressed due to low confidence (1)

bullet-featherstone/src/SDFFeatures.cc:862

  • The new null check guards the property assignments, but joint->Axis() is still dereferenced unconditionally when creating btMultiBodyJointLimitConstraint. If Axis() can be nullptr for any non-ball joint (e.g., malformed SDF), this will still segfault. Consider caching axis = joint->Axis() once and only creating the limit constraint when axis is non-null (otherwise skip and emit an error/warning).
        if (::sdf::JointType::BALL != joint->Type())
        {
          jointInfo->jointLimits =
            std::make_shared<btMultiBodyJointLimitConstraint>(
              model->body.get(), i,
              static_cast<btScalar>(joint->Axis()->Lower()),
              static_cast<btScalar>(joint->Axis()->Upper()));
          world->world->addMultiBodyConstraint(jointInfo->jointLimits.get());

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +831 to +852
if (joint->Axis())
{
model->body->getLink(i).m_jointLowerLimit =
static_cast<btScalar>(joint->Axis()->Lower());
model->body->getLink(i).m_jointUpperLimit =
static_cast<btScalar>(joint->Axis()->Upper());
model->body->getLink(i).m_jointFriction =
static_cast<btScalar>(joint->Axis()->Friction());
model->body->getLink(i).m_jointMaxVelocity =
static_cast<btScalar>(joint->Axis()->MaxVelocity());
model->body->getLink(i).m_jointMaxForce =
static_cast<btScalar>(joint->Axis()->Effort());

jointInfo->minEffort = -joint->Axis()->Effort();
jointInfo->maxEffort = joint->Axis()->Effort();
jointInfo->minVelocity = -joint->Axis()->MaxVelocity();
jointInfo->maxVelocity = joint->Axis()->MaxVelocity();
jointInfo->axisLower = joint->Axis()->Lower();
jointInfo->axisUpper = joint->Axis()->Upper();
jointInfo->damping = joint->Axis()->Damping();
jointInfo->springStiffness = joint->Axis()->SpringStiffness();
jointInfo->springReference = joint->Axis()->SpringReference();

Copilot AI Feb 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Within the if (joint->Axis()) block, joint->Axis() is called repeatedly. Caching the pointer/reference once (e.g., const auto *axis = joint->Axis();) will make the code clearer and avoids repeated virtual calls / pointer chasing.

Copilot uses AI. Check for mistakes.
@@ -828,26 +828,29 @@ Identity SDFFeatures::ConstructSdfModelImpl(
// bullet-featherstone and so setting them does not have any effect.
// The lower and uppper limit is supported via the

Copilot AI Feb 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in comment: "uppper" should be "upper".

Suggested change
// The lower and uppper limit is supported via the
// The lower and upper limit is supported via the

Copilot uses AI. Check for mistakes.
Comment on lines +831 to +833
if (joint->Axis())
{
model->body->getLink(i).m_jointLowerLimit =

Copilot AI Feb 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change fixes a crash during SDF model construction for ball joints with no axis; please add a regression test that loads an SDF/world containing a ball joint without an <axis> using the bullet-featherstone engine and asserts ConstructWorld (or ConstructModel) succeeds without crashing.

Copilot uses AI. Check for mistakes.
@github-project-automation github-project-automation Bot moved this from Inbox to In review in Core development Feb 12, 2026
@iche033
iche033 merged commit 2f8e332 into gazebosim:main Feb 12, 2026
12 checks passed
@github-project-automation github-project-automation Bot moved this from In review to Done in Core development Feb 12, 2026
@iche033

iche033 commented Feb 12, 2026

Copy link
Copy Markdown
Contributor

@Mergifyio backport gz-physics9 gz-physics8 gz-physics7

@mergify

mergify Bot commented Feb 12, 2026

Copy link
Copy Markdown
Contributor

backport gz-physics9 gz-physics8 gz-physics7

✅ Backports have been created

Details

mergify Bot pushed a commit that referenced this pull request Feb 12, 2026
)

Signed-off-by: momo <2438833481@qq.com>
(cherry picked from commit 2f8e332)
mergify Bot pushed a commit that referenced this pull request Feb 12, 2026
)

Signed-off-by: momo <2438833481@qq.com>
(cherry picked from commit 2f8e332)
mergify Bot pushed a commit that referenced this pull request Feb 12, 2026
)

Signed-off-by: momo <2438833481@qq.com>
(cherry picked from commit 2f8e332)
@XINJIANGMO
XINJIANGMO deleted the fixbug-864 branch February 13, 2026 01:08
iche033 pushed a commit that referenced this pull request Feb 13, 2026
)

Signed-off-by: momo <2438833481@qq.com>
(cherry picked from commit 2f8e332)
iche033 pushed a commit that referenced this pull request Feb 13, 2026
)

Signed-off-by: momo <2438833481@qq.com>
(cherry picked from commit 2f8e332)
iche033 pushed a commit that referenced this pull request Feb 13, 2026
)

Signed-off-by: momo <2438833481@qq.com>
(cherry picked from commit 2f8e332)
mderbaso-deepx pushed a commit to DeepX-inc/gz-physics that referenced this pull request Apr 13, 2026
…azebosim#868)

Signed-off-by: momo <2438833481@qq.com>
(cherry picked from commit 2f8e332)
j-rivero pushed a commit that referenced this pull request Apr 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

4 participants