eranpeer / FakeIt

C++ mocking made easy. A simple yet very expressive, headers only library for c++ mocking.
MIT License
1.22k stars 170 forks source link

Disarm UBSAN for VirtualOffsetSelector cast #261

Closed gjasny closed 1 year ago

gjasny commented 2 years ago

Otherswise Clang will report the following:

.../include/standalone/fakeit.hpp:5337:47: runtime error: member call on address 0x7ffc27172e08 which does not point to an object of type 'rtc::test::tpsclient::ITestCaseHandler'
0x7ffc27172e08: note: object is of type 'fakeit::VirtualOffsetSelector'
 00 00 00 00  38 b1 5e 00 00 00 00 00  10 c0 91 01 00 00 00 00  10 c0 91 01 00 00 00 00  f8 1d 05 01
              ^~~~~~~~~~~~~~~~~~~~~~~
              vptr for 'fakeit::VirtualOffsetSelector'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior .../include/standalone/fakeit.hpp:5337:47 in

A reproducer:

#include <catch2/catch.hpp>
#include <catch/fakeit.hpp>

class ITestCaseHandler
{
public:
    virtual ~ITestCaseHandler() = default;
    virtual void adaptVideoBandwidth(const std::shared_ptr<int>& foo) = 0;
};

SCENARIO("MyFixture", "[UnitTest]")
{
    fakeit::Mock<ITestCaseHandler> mockTestCaseHandler;
}

Compiled with clang++-12 -fsanitize=undefined -std=c++17 -O2 -DNDEBUG.

malcolmdavey commented 2 years ago

Do the existing unit tests trigger this as well?

gjasny commented 2 years ago

Yep:

(tested with clang++-14 and -fsanitize=undefined)

[ RUN          ] Miscellaneous::mock_virtual_methods_of_base_class
../../include/mockutils/VTUtils.hpp:43:47: runtime error: member call on address 0x7ffccb5d94d0 which does not point to an object of type 'Miscellaneous::B'
0x7ffccb5d94d0: note: object is of type 'fakeit::VirtualOffsetSelector'
 73 55 00 00  70 6e 11 dd 73 55 00 00  20 f7 33 df 73 55 00 00  20 f7 33 df 73 55 00 00  88 2e 33 df
              ^~~~~~~~~~~~~~~~~~~~~~~
              vptr for 'fakeit::VirtualOffsetSelector'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior ../../include/mockutils/VTUtils.hpp:43:47 in 
[       PASSED ] Miscellaneous::mock_virtual_methods_of_base_class

It vanishes with my patch.

BTW: There was another (unrelated) finding:

[ RUN          ] DefaultBehavioreTests::ReturnByReference_ReturnReferenceToNullIfAbstract
../../include/mockutils/DefaultValue.hpp:38:24: runtime error: reference binding to null pointer of type 'typename naked_type<ReferenceFunctions &>::type' (aka 'DefaultBehavioreTests::ReferenceFunctions')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior ../../include/mockutils/DefaultValue.hpp:38:24 in 
../../include/fakeit/Action.hpp:83:20: runtime error: reference binding to null pointer of type 'DefaultBehavioreTests::ReferenceFunctions'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior ../../include/fakeit/Action.hpp:83:20 in 
[              ]    assertion #1 at ../default_behaviore_tests.cpp:195
[       FAILED ] DefaultBehavioreTests::ReturnByReference_ReturnReferenceToNullIfAbstract