Skip to content

Fix segfault on a mesh with convex inertia that no geom references - #3432

Open
VihaanAgarwal wants to merge 1 commit into
google-deepmind:mainfrom
VihaanAgarwal:fix/convex-inertia-unreferenced-mesh
Open

Fix segfault on a mesh with convex inertia that no geom references#3432
VihaanAgarwal wants to merge 1 commit into
google-deepmind:mainfrom
VihaanAgarwal:fix/convex-inertia-unreferenced-mesh

Conversation

@VihaanAgarwal

Copy link
Copy Markdown

Fixes #3431.

What happens

A mesh declared with inertia="convex" that no geom references segfaults the compiler:

<mujoco>
  <asset>
    <mesh name="orphan" inertia="convex"
          vertex="0 0 1   1 0 0   0 1 0   -1 0 0   0 -1 0"
          face="0 1 2   0 2 3   0 3 4   0 4 1   1 4 3   1 3 2"/>
  </asset>
  <worldbody/>
</mujoco>

mujoco.MjModel.from_xml_path("orphan.xml") exits with SIGSEGV on 3.10.0 and on current main.

Root cause

mjCModel::TryCompile decides which meshes need a convex hull by walking geoms_, and one of the
conditions in that loop is geoms_[i]->mesh->spec.inertia == mjMESH_INERTIA_CONVEX. That condition
is a property of the mesh, but it is only ever evaluated for meshes some geom points at. An
unreferenced mesh is never visited, so needhull_ stays false, mjCMesh::Compile skips
MakeGraph, and graph_ stays null. ComputeVolume and ComputeInertia then do

int nf = (inertia == mjMESH_INERTIA_CONVEX) ? graph_[1] : nface();
const int* f = (inertia == mjMESH_INERTIA_CONVEX) ? GraphFaces() : face_.data();

on that null pointer, which is the crash. Note the mesh here has faces, so the face_.empty()
fallback that would otherwise build the hull does not fire either.

Fix

Move the convex-inertia condition out of the geom loop and apply it to every mesh, so a mesh that
computes its inertia from its hull always gets one. The geom loop keeps the conditions that really
are about geoms (contype, conaffinity, membership in a contact pair).

The reporter asked for "a warning about unused meshes, or silence" — this gives silence, and it
matches the intent the original condition already expressed.

Test

MjCMeshTest.UnreferencedConvexInertiaMesh in test/user/user_mesh_test.cc compiles the model
above. It dies with SIGSEGV on main and passes with this change.

Ran on macOS arm64, Release build:

  • user_mesh_test 71/71 pass
  • user_objects_test 90/90, user_recompile_test 320/320, user_flex_test 59/59,
    user_composite_test 4/4 all pass
  • user_model_test has one failure (MujocoTest.ResolvePluginMissingInstanceThrowsError) and
    user_api_test segfaults, both of which reproduce identically on unmodified main here, so they
    are local/environmental and not from this change.

Changelog entry added under Compiler -> Bug fixes.

@google-cla

google-cla Bot commented Jul 26, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@VihaanAgarwal

Copy link
Copy Markdown
Author

Hey, I get the suspicion. I did use a coding agent to help me navigate the codebase, but I wasn't just submitting whatever it generated.

It took me a while to track this down: graph_ is null because the geom loop in TryCompile only checks the convex-inertia condition for meshes referenced by a geom. For an orphan mesh, needhull_ never gets set.

The test segfaults on main and passes with the change.

This is my first time working in a C++ codebase this large, so if the fix itself or the test placement is off, just let me know and I'll redo it.

@VihaanAgarwal

Copy link
Copy Markdown
Author

?

@VihaanAgarwal

Copy link
Copy Markdown
Author

Yeah, I use Claude Code. It’s 2026. If there’s an issue with the actual fix, I’m happy to address it.

needhull_ was only set while iterating geoms, so a mesh whose inertia is
computed from its convex hull never got one unless some geom pointed at
it. mjCMesh::ComputeVolume and ComputeInertia then read graph_[1] and
GraphFaces() off a null pointer and the compiler crashed.

Whether a mesh needs its hull for inertia is a property of the mesh, not
of any geom, so move that condition out of the geom loop and apply it to
every mesh.

Fixes google-deepmind#3431
@VihaanAgarwal
VihaanAgarwal force-pushed the fix/convex-inertia-unreferenced-mesh branch from 977745b to 95f0540 Compare July 29, 2026 00:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Segmentation fault on unreferenced mesh with inertia="convex"

1 participant