Skip to content

Commit

Permalink
Fix null being passed to memcpy (#770)
Browse files Browse the repository at this point in the history
Joints were incorrectly using the body bit-set for the overflow color
Sensor shapes now always generate events when created
  • Loading branch information
erincatto authored Aug 16, 2024
1 parent 8e7a17c commit 2b880d1
Show file tree
Hide file tree
Showing 10 changed files with 31 additions and 14 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
# Box2D
Box2D is a 2D physics engine for games.

[![Box2D Version 3.0 Release Demo](https://img.youtube.com/vi/dAoM-xjOWtA/0.jpg)](https://www.youtube.com/watch?v=dAoM-xjOWtA)

## Features

### Collision
Expand Down
1 change: 1 addition & 0 deletions include/box2d/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ typedef struct b2ShapeDef
/// Normally shapes on static bodies don't invoke contact creation when they are added to the world. This overrides
/// that behavior and causes contact creation. This significantly slows down static body creation which can be important
/// when there are many static shapes.
/// This is implicitly always true for sensors.
bool forceContactCreation;

/// Used internally to detect a valid definition. DO NOT SET.
Expand Down
2 changes: 2 additions & 0 deletions samples/sample_continuous.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ class BounceHouse : public Sample
m_bodyId = b2_nullBodyId;
m_enableHitEvents = true;

memset( m_hitEvents, 0, sizeof( m_hitEvents ) );

Launch();
}

Expand Down
3 changes: 2 additions & 1 deletion src/bitset.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ void b2GrowBitSet( b2BitSet* bitSet, uint32_t blockCount )
bitSet->blockCapacity = blockCount + blockCount / 2;
uint64_t* newBits = b2Alloc( bitSet->blockCapacity * sizeof( uint64_t ) );
memset( newBits, 0, bitSet->blockCapacity * sizeof( uint64_t ) );
memcpy( newBits, bitSet->bits, bitSet->blockCount * sizeof( uint64_t ) );
B2_ASSERT( bitSet->bits != NULL );
memcpy( newBits, bitSet->bits, oldCapacity * sizeof( uint64_t ) );
b2Free( bitSet->bits, oldCapacity * sizeof( uint64_t ) );
bitSet->bits = newBits;
}
Expand Down
2 changes: 1 addition & 1 deletion src/bitset.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include <stdbool.h>
#include <stdint.h>

// Bit set provides fast operations on large arrays of bits
// Bit set provides fast operations on large arrays of bits.
typedef struct b2BitSet
{
uint64_t* bits;
Expand Down
5 changes: 5 additions & 0 deletions src/block_array.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ b2BodySim* b2AddBodySim( b2BodySimArray* array )
{
int newCapacity = 2 * array->capacity;
b2BodySim* newElements = b2Alloc( newCapacity * elementSize );
B2_ASSERT( array->data != NULL );
memcpy( newElements, array->data, array->capacity * elementSize );
b2Free( array->data, array->capacity * elementSize );
array->data = newElements;
Expand All @@ -126,6 +127,7 @@ b2BodyState* b2AddBodyState( b2BodyStateArray* array )
{
int newCapacity = 2 * array->capacity;
b2BodyState* newElements = b2Alloc( newCapacity * elementSize );
B2_ASSERT( array->data != NULL );
memcpy( newElements, array->data, array->capacity * elementSize );
b2Free( array->data, array->capacity * elementSize );
array->data = newElements;
Expand All @@ -150,6 +152,7 @@ b2ContactSim* b2AddContact( b2ContactArray* array )
{
int newCapacity = 2 * array->capacity;
b2ContactSim* newElements = b2Alloc( newCapacity * elementSize );
B2_ASSERT( array->data != NULL );
memcpy( newElements, array->data, array->capacity * elementSize );
b2Free( array->data, array->capacity * elementSize );
array->data = newElements;
Expand All @@ -174,6 +177,7 @@ b2JointSim* b2AddJoint( b2JointArray* array )
{
int newCapacity = 2 * array->capacity;
b2JointSim* newElements = b2Alloc( newCapacity * elementSize );
B2_ASSERT( array->data != NULL );
memcpy( newElements, array->data, array->capacity * elementSize );
b2Free( array->data, array->capacity * elementSize );
array->data = newElements;
Expand All @@ -198,6 +202,7 @@ b2IslandSim* b2AddIsland( b2IslandArray* array )
{
int newCapacity = 2 * array->capacity;
b2IslandSim* newElements = b2Alloc( newCapacity * elementSize );
B2_ASSERT( array->data != NULL );
memcpy( newElements, array->data, array->capacity * elementSize );
b2Free( array->data, array->capacity * elementSize );
array->data = newElements;
Expand Down
24 changes: 14 additions & 10 deletions src/constraint_graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,19 @@ _Static_assert( b2_graphColorCount == 12, "graph color count assumed to be 12" )
void b2CreateGraph( b2ConstraintGraph* graph, int bodyCapacity )
{
_Static_assert( b2_graphColorCount >= 2, "must have at least two constraint graph colors" );
_Static_assert( b2_overflowIndex == b2_graphColorCount - 1, "bad over flow index");

*graph = ( b2ConstraintGraph ){ 0 };

bodyCapacity = b2MaxInt( bodyCapacity, 8 );
for ( int i = 0; i < b2_graphColorCount; ++i )

// Initialize graph color bit set.
// No bitset for overflow color.
for ( int i = 0; i < b2_overflowIndex; ++i )
{
b2GraphColor* color = graph->colors + i;

if ( i != b2_overflowIndex )
{
color->bodySet = b2CreateBitSet( bodyCapacity );
b2SetBitCountAndClear( &color->bodySet, bodyCapacity );
}
color->bodySet = b2CreateBitSet( bodyCapacity );
b2SetBitCountAndClear( &color->bodySet, bodyCapacity );
}
}

Expand All @@ -51,6 +51,10 @@ void b2DestroyGraph( b2ConstraintGraph* graph )
for ( int i = 0; i < b2_graphColorCount; ++i )
{
b2GraphColor* color = graph->colors + i;

// The bit set should never be used on the overflow color
B2_ASSERT( i != b2_overflowIndex || color->bodySet.bits == NULL );

b2DestroyBitSet( &color->bodySet );

b2DestroyContactArray( &color->contacts );
Expand Down Expand Up @@ -220,7 +224,7 @@ static int b2AssignJointColor( b2ConstraintGraph* graph, int bodyIdA, int bodyId
#if B2_FORCE_OVERFLOW == 0
if ( staticA == false && staticB == false )
{
for ( int i = 0; i < b2_graphColorCount; ++i )
for ( int i = 0; i < b2_overflowIndex; ++i )
{
b2GraphColor* color = graph->colors + i;
if ( b2GetBit( &color->bodySet, bodyIdA ) || b2GetBit( &color->bodySet, bodyIdB ) )
Expand All @@ -235,7 +239,7 @@ static int b2AssignJointColor( b2ConstraintGraph* graph, int bodyIdA, int bodyId
}
else if ( staticA == false )
{
for ( int i = 0; i < b2_graphColorCount; ++i )
for ( int i = 0; i < b2_overflowIndex; ++i )
{
b2GraphColor* color = graph->colors + i;
if ( b2GetBit( &color->bodySet, bodyIdA ) )
Expand All @@ -249,7 +253,7 @@ static int b2AssignJointColor( b2ConstraintGraph* graph, int bodyIdA, int bodyId
}
else if ( staticB == false )
{
for ( int i = 0; i < b2_graphColorCount; ++i )
for ( int i = 0; i < b2_overflowIndex; ++i )
{
b2GraphColor* color = graph->colors + i;
if ( b2GetBit( &color->bodySet, bodyIdB ) )
Expand Down
3 changes: 2 additions & 1 deletion src/constraint_graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ typedef struct b2World b2World;

typedef struct b2GraphColor
{
// base on bodyId so this is over-sized to encompass static bodies
// This bitset is indexed by bodyId so this is over-sized to encompass static bodies
// however I never traverse these bits or use the bit count for anything
// This bitset is unused on the overflow color.
b2BitSet bodySet;

// cache friendly arrays
Expand Down
1 change: 1 addition & 0 deletions src/dynamic_tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ static int32_t b2AllocateNode( b2DynamicTree* tree )
int32_t oldCapcity = tree->nodeCapacity;
tree->nodeCapacity += oldCapcity >> 1;
tree->nodes = (b2TreeNode*)b2Alloc( tree->nodeCapacity * sizeof( b2TreeNode ) );
B2_ASSERT( oldNodes != NULL );
memcpy( tree->nodes, oldNodes, tree->nodeCount * sizeof( b2TreeNode ) );
b2Free( oldNodes, oldCapcity * sizeof( b2TreeNode ) );

Expand Down
2 changes: 1 addition & 1 deletion src/shape.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ static b2Shape* b2CreateShapeInternal( b2World* world, b2Body* body, b2Transform
if ( body->setIndex != b2_disabledSet )
{
b2BodyType proxyType = body->type;
b2CreateShapeProxy( shape, &world->broadPhase, proxyType, transform, def->forceContactCreation );
b2CreateShapeProxy( shape, &world->broadPhase, proxyType, transform, def->forceContactCreation || def->isSensor );
}

// Add to shape doubly linked list
Expand Down

0 comments on commit 2b880d1

Please sign in to comment.