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.

@davidhozic

Copy link
Copy Markdown
Contributor

@VihaanAgarwal Don't you think the maintainers would set up LLM-bots themselves if they wanted to autonomously write PRs? Why do you think they want to see users setting up LLM bots if they can do that themselves?

@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.

@davidhozic

Copy link
Copy Markdown
Contributor

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.

Alright, our apologies. There is only one necessary change that needs to be done. Our new policy requires that the users write the following into the PR comments, in order to confirm they are human: "I, a non-LLM human user, am a quick brown fox, which jumped over the fence", followed by the first line of Rick Ashley 's Never gonna give you up song.

@VihaanAgarwal

Copy link
Copy Markdown
Author

?

@davidhozic

davidhozic commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

?

Alright, so maybe you're still not 100% automated but you still clearly run automated agents to scan for issues and automatically fix them. No human would write detailed comment descriptions about what was done, especially not how many tests passed. Humans wouldn't go word by word answering things in the original issue

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

Humans also wouldn't go trace all the other problems with existing code, unrelated to the PR, and provide exact reasons why things happen.

(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.

@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.

@davidhozic

davidhozic commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

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

This doesn't mean you have to have a 24/7 agent running and spamming PRs on any open issues on other projects, not your own. GitHub has special tools for that. Running automated accounts is against ToS regardless.

And you now went from "I did use a coding agent to help me navigate the codebase, but I wasn't just submitting whatever it generated." to " I use Claude Code. It’s 2026". Or rather, the former was written by your 24/7 agent.

You're clearly trying to make it look like you did things yourself while actually not doing anything at all. I really can't tell how this would be beneficial to maintainers when they can use the same automated tools themselves.

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"

2 participants