Undefined behavior when two bodies collide

Issue #85 resolved
Ian McFarlane created an issue

I have used ODE in the past with cmake and clang, but recently I switched to zig (which is both a C/C++ compiler and build system, and a few other things). zig enables ubsan by default, though, and I discovered that my game project was crashing whenever two geometries collided (in debug mode). Here is the valgrind output:

==96739== Conditional jump or move depends on uninitialised value(s)
==96739==    at 0x60A416: std::__1::enable_if<is_move_constructible<bool>::value&&is_move_assignable<bool>::value, void>::type std::__1::swap[abi:v160001]<bool>(bool&, bool&) (swap.h:39)
==96739==    by 0x60A2C2: void dxSwap<bool>(bool&, bool&) (common.h:353)
==96739==    by 0x5F4E6E: swapProblem(float**, float*, float*, float*, unsigned int*, bool*, int*, unsigned int, unsigned int, unsigned int, unsigned int, int) (lcp.cpp:260)
==96739==    by 0x5F4684: dLCP::dLCP(unsigned int, unsigned int, unsigned int, float*, float*, float*, float*, float*, float*, float*, float*, float*, bool*, int*, unsigned int*, unsigned int*, float**) (lcp.cpp:501)
==96739==    by 0x5F8DF6: dxSolveLCP_Generic(dxWorldProcessMemArena*, unsigned int, float*, float*, float*, unsigned int, float*, int*) (lcp.cpp:868)
==96739==    by 0x5F83D0: dxSolveLCP(dxWorldProcessMemArena*, unsigned int, float*, float*, float*, unsigned int, float*, int*) (lcp.cpp:810)
==96739==    by 0x5EE359: dxStepIsland_Stage3(dxStepperStage3CallContext*) (step.cpp:1459)
==96739==    by 0x5E524D: dxStepIsland_Stage1(dxStepperStage1CallContext*) (step.cpp:979)
==96739==    by 0x5DDD7D: dxStepIsland(dxStepperProcessingCallContext const*) (step.cpp:546)
==96739==    by 0x3E367C: dxIslandsProcessingCallContext::ThreadedProcessIslandStepper(dxSingleIslandCallContext*) (util.cpp:1065)
==96739==    by 0x3E35BA: dxIslandsProcessingCallContext::ThreadedProcessIslandStepper_Callback(void*, unsigned long, dxCallReleasee*) (util.cpp:1059)
==96739==    by 0x531C53: dxThreadedJobInfo::InvokeCallFunction() (threading_impl_templates.h:174)
==96739==  Uninitialised value was created by a heap allocation
==96739==    at 0x484279B: malloc (in /nix/store/ynr198i5gi45hd16hzcxp5nn6dhfmvrm-valgrind-3.20.0/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==96739==    by 0x3D6A89: dAlloc (memory.cpp:80)
==96739==    by 0x3D89CD: dxWorldProcessMemArena::ReallocateMemArena(dxWorldProcessMemArena*, unsigned long, dxWorldProcessMemoryManager const*, float, unsigned int) (util.cpp:1111)
==96739==    by 0x3D8F8F: dxWorldProcessContext::ReallocateStepperMemArenas(dxWorld*, unsigned int, unsigned long, dxWorldProcessMemoryManager const*, float, unsigned int) (util.cpp:250)
==96739==    by 0x3E3DE5: dxReallocateWorldProcessContext(dxWorld*, dxWorldProcessIslandsInfo&, float, unsigned long (*)(dxBody* const*, unsigned int, dxJoint* const*, unsigned int)) (util.cpp:1205)
==96739==    by 0x3CB00E: dWorldStep (ode.cpp:1836)
==96739==    by 0x3AFB61: level::update() (level.cpp:163)
==96739==    by 0x2BDBA0: update() (main.cpp:56)
==96739==    by 0x2BDB22: main (main.cpp:28)

Reproducing the issue

Here is my repository, which includes ODE as a submodule so it should be cloned with --recursive. Once you have it cloned, check out commit 1dbf0de21aae3e0320209287b986afd3d67be54e. Grab a zig v11-dev binary from the zig website or build it from source (I use commit 7dd1cf26f9b0cb104ada166a10ff356ca272577a).Then runzig build -DODE-demos=true which will build the whole project in debug mode including the ODE demos, which will be deposited in zig-out/bin. Unfortunately you will have to fix the path to the resources folder before the demos will run.

Comments (3)

  1. Oleh Derevenko

    It’s cosmetic as the m_state array is not initialized yet at all at that point. But I’ve made some changes so that your validator did not fail.

  2. Log in to comment