Repository navigation
Conversation
When a body is removed after saveState, its multibody slot is freed and can be reused by a newly loaded body. restoreState validates the snapshot against the existing world using only the multibody count and per-body link counts, so a different body reusing the freed slot passes validation when its link count happens to match. The restore then silently overwrites the new body's multibody state (mass, pose, velocities) with the saved body's state, losing the new body without any error. Reproduced with pybullet in DIRECT mode: load cube.urdf, saveState, removeBody, load sphere2.urdf (which reuses the freed slot), then restoreState. The restore succeeds and afterwards the slot holds the cube's state; the sphere is gone. Without a removal in between, a body count mismatch makes restoreState fail with an error, so the silent overwrite is inconsistent with the existing failure mode. Record the collider shape types of each multibody slot (base collider and link colliders) in SaveStateData when a state is saved, and refuse a restore whose slots no longer match the current world, reporting CMD_RESTORE_STATE_FAILED with a warning instead of corrupting state. The check compares shape types, so it rejects reuse by a differently shaped body while still allowing a restore onto an identically shaped body. Scope note: restoreState from a .bullet file has the same validation gap, but pybullet's own saveBullet output does not serialize multibody collider data to validate against, so the file path is not covered here. Adds a regression test that saves state, removes a body, loads a differently shaped body into the freed slot and requires restoreState to raise pybullet.error and leave the world untouched. The test fails at baseline and passes with the fix.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When a body is removed after
saveState, its multibody slot is freed and can be reused by a newly loaded body.restoreStatevalidates the snapshot against the existing world using only the multibody count and per-body link counts, so a different body reusing the freed slot passes validation when its link count happens to match. The restore then silently overwrites the new body's multibody state (mass, pose, velocities) with the saved body's state, losing the new body without any error.Reproduced in DIRECT mode:
Without a removal in between, a body count mismatch makes
restoreStatefail with an error, so the silent overwrite is inconsistent with the existing failure mode.Fix
Record the collider shape types of each multibody slot (base collider and link colliders) in
SaveStateDatawhen a state is saved, and refuse a restore whose slots no longer match the current world, reportingCMD_RESTORE_STATE_FAILEDwith a warning instead of corrupting state. The check compares shape types, so it rejects reuse by a differently shaped body while still allowing a restore onto an identically shaped body.Tests
saveRestoreStateTest.py: saves state, removes a body, loads a differently shaped body into the freed slot and requiresrestoreStateto raisepybullet.errorand leave the world untouched. The test fails at baseline and passes with the fix.saveRestoreStateTest.py,unittests.pyanduserDataTest.pysuites all pass.Scope
restoreStatefrom a.bulletfile has the same validation gap, but pybullet's ownsaveBulletoutput does not serialize multibody collider shape data to validate against, so the file path is not covered here.