Skip to content

Null dereferences when mocking C-style string arguments #115

@AlexSmithEtas

Description

@AlexSmithEtas

Mocking methods / functions that take C-style string (i.e. char*) arguments can lead to null dereferences, in some cases where nullptr is expected and / or actually passed.

When a mock method / function is configured to expect a call with a non-null string, a nullptr dereference occurs in the case that the code under test incorrectly passes nullptr. Compare and contrast the behaviour of the following:

MOCK_FUNCTION( f, 1, void( const char* ) );

BOOST_FIXTURE_TEST_CASE( expect_non_null_get_non_null, mock::cleanup )
{
    mock::sequence s;
    MOCK_EXPECT( f ).once().in( s ).with( "correct" );

    f( "wrong" );

    mock::verify();
    // We are correctly told that the `code under test' called f() with the
    // string "wrong" when it should have passed "correct".
}

BOOST_FIXTURE_TEST_CASE( expect_non_null_get_null, mock::cleanup )
{
    mock::sequence s;
    MOCK_EXPECT( f ).once().in( s ).with( "test" );

    f( nullptr );

    mock::verify();
    // Bang! nullptr is dereferenced.
}

When a mock method / function is configured to expect character pointer nullptr to be passed to a C-style string argument, a nullptr dereference occurs, regardless of whether the code under test passes nullptr or a non-null string. Note that this does not occur when nullptr_t nullptr is expected, so is only a problem when e.g. a constant or definition that is more natural to the particular situation is used in the expectation, rather than explicitly expecting nullptr. Compare and contrast the behaviour of the following:

// From some third-party API header:
typedef const char* some_api_string;
#define SOME_API_NO_STRING ( (const char*) NULL )

MOCK_FUNCTION( f, 1, void( some_api_string ) );

BOOST_FIXTURE_TEST_CASE( expect_nullptr_get_null, mock::cleanup )
{
    mock::sequence s;
    MOCK_EXPECT( f ).once().in( s ).with( nullptr );

    f( SOME_API_NO_STRING );

    mock::verify();
    // We are correctly told that the test passed.
}

BOOST_FIXTURE_TEST_CASE( expect_null_get_null, mock::cleanup )
{
    mock::sequence s;
    MOCK_EXPECT( f ).once().in( s ).with( SOME_API_NO_STRING );

    f( SOME_API_NO_STRING );

    mock::verify();
    // Bang! nullptr is dereferenced.
}

BOOST_FIXTURE_TEST_CASE( expect_null_get_non_null, mock::cleanup )
{
    mock::sequence s;
    MOCK_EXPECT( f ).once().in( s ).with( SOME_API_NO_STRING );

    f( "wrong" );

    mock::verify();
    // Bang! nullptr is dereferenced.
}

These nullptr dereferences occur because there are no runtime checks for the nullptr cases in the matcher and serializer for C-style strings. Pull request to follow.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions