Skip to content

Instantly share code, notes, and snippets.

@RossBencina
Created October 15, 2016 10:28
Show Gist options
  • Save RossBencina/3d75caa85293685eb3a55365b47954a5 to your computer and use it in GitHub Desktop.
Save RossBencina/3d75caa85293685eb3a55365b47954a5 to your computer and use it in GitHub Desktop.
// These are reduced test cases derived from a work-in-progress (non-production) code base.
// Can you spot the bugs that PVS-Studio found?
#include <atomic>
#include "catch.hpp"
///////////////////////////////////////////////////////////////////////////////
// Bug #1
class Test { // Dummy type for testing.
int x_;
public:
Test() : x_(0) {}
int x() const { return x_; }
};
// The purpose of allocateObjectEtc() is to perform various initialization and
// allocate and return a Test instance (or return nullptr on error).
static Test *v688_allocateObjectEtc_BUG()
{
// ... do work ...
Test *result = new Test();
if( !result ){
// ... cleanup work ...
return nullptr;
}
// ... do more work ...
return result;
}
TEST_CASE( "pvs-studio-eval/v688/bug", "[pvs-studio-eval] allocate an object" ) {
Test *t = v688_allocateObjectEtc_BUG();
if (t) {
REQUIRE( t->x() == 0 );
delete t;
}
}
///////////////////////////////////////////////////////////////////////////////
// Bug #2
// SharedDataBuffer is a header for buffers that are shared between threads
// with reference counting. Allocation is deferred via a lock-free queue.
// Note: In this test case the deallocation and refCount methods are not used.
struct SharedDataBuffer{
typedef void (*DeallocateFunctionPtr)( SharedDataBuffer *buffer );
union {
DeallocateFunctionPtr asyncDeallocFn;
void *next; // deallocted buffers get put on a lock-free queue
};
std::atomic<std::size_t> refCount;
std::size_t dataCapacityBytes; // includes the entire allocated length of data
char data[1]; // data area. not necessarily null terminated
};
struct ContainedType {
size_t field_a;
// ...
double field_z;
// ...
};
// Allocate a SharedDataBuffer used to store ContainedType struct.
// You should call getContained_BUG() to extract a ContainedType ptr from a
// shared buffer allocated by this function.
static SharedDataBuffer *v119_compositeAllocation_BUG()
{
size_t allocSize = sizeof(SharedDataBuffer) + sizeof(ContainedType);
SharedDataBuffer *result = reinterpret_cast<SharedDataBuffer*>(new (std::nothrow) char[allocSize]);
if (result) {
// ... init dealloc proc and refcount ...
result->dataCapacityBytes = sizeof(ContainedType);
}
return result;
}
ContainedType* getContained_BUG(SharedDataBuffer *buffer)
{
return reinterpret_cast<ContainedType*>(&buffer->data[0]);
}
TEST_CASE( "pvs-studio-eval/v119", "[pvs-studio-eval] test composite allocation" ) {
SharedDataBuffer *b = v119_compositeAllocation_BUG();
REQUIRE( b->dataCapacityBytes == sizeof(ContainedType) );
ContainedType *c = getContained_BUG(b);
c->field_a = 0;
c->field_z = 1.0;
delete [] b;
}
///////////////////////////////////////////////////////////////////////////////
// Bug #3
void testFooFunction(int)
{
// ... do stuff ...
}
TEST_CASE( "pvs-studio-eval/v524/test-foo-function", "[pvs-studio-eval] run parameterised tests on foo function" ) {
testFooFunction(1);
testFooFunction(2);
testFooFunction(3);
}
void testBarFunction(int)
{
// ... do stuff ...
}
TEST_CASE( "pvs-studio-eval/v524/test-bar-function", "[pvs-studio-eval] run parameterised tests on bar function" ) {
testFooFunction(1);
testFooFunction(2);
testFooFunction(3);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment