coolxv / cpp-stub

C++ unit test stub(not mock) and awesome.Surpported ISA x86,x86-64,arm64,arm32,arm thumb,mips64,riscv,loongarch64.
MIT License
280 stars 82 forks source link

Store to misaligned address in `REPLACE_NEAR` macro #21

Open jiridanek opened 2 years ago

jiridanek commented 2 years ago

I am using amd64 architecture. I enabled AddressSanitizer and UndefinedBehavior sanitizer in GCC. My tests produce the following undefined behavior error:

cpp_stub.h:244:13: runtime error: store to misaligned address 0x0000004bc2e1 for type 'int', which requires 4 byte alignment
0x0000004bc2e1: note: pointer points here
 fd ff ff  e9 25 8a 3e 69 00 68 2b  00 00 00 e9 30 fd ff ff  ff 25 82 3e 69 00 68 2c  00 00 00 e9 20
              ^ 
pc_0x9534d7###func_void Stub::set<int (*)(char*, unsigned long, char const*, __va_list_tag*), int (*)(char*, unsigned long, char const*, ...)>(int (*)(char*, unsigned long, char const*, __va_list_tag*), int (*)(char*, unsigned long, char const*, ...))###file_/home/jdanek/repos/qpid/qpid-dispatch/tests/cpp-stub/cpp_stub.h###line_244###obj_(c_unittests+0x9534d7)
pc_0x94cb4b###func__DOCTEST_ANON_FUNC_2###file_/home/jdanek/repos/qpid/qpid-dispatch/tests/c_unittests/test_terminus.cpp###line_88###obj_(c_unittests+0x94cb4b)
pc_0x7fc0ce###func_doctest::Context::run()###file_/home/jdanek/repos/qpid/qpid-dispatch/tests/c_unittests/doctest.h###line_6486###obj_(c_unittests+0x7fc0ce)
pc_0x7ff7c0###func_main###file_/home/jdanek/repos/qpid/qpid-dispatch/tests/c_unittests/doctest.h###line_6571###obj_(c_unittests+0x7ff7c0)
pc_0x7f11e90db55f###func___libc_start_call_main###file_<null>###line_0###obj_(libc.so.6+0x2d55f)
pc_0x7f11e90db60b###func___libc_start_main_impl###file_<null>###line_0###obj_(libc.so.6+0x2d60b)
pc_0x4bec64###func__start###file_<null>###line_0###obj_(c_unittests+0x4bec64)

The stub.cpp code is

REPLACE_NEAR(this, fn, fn_stub);

The macro is

    //5 byte(jmp rel32)
    #define REPLACE_NEAR(t, fn, fn_stub)\
        *fn = 0xE9;\
        *(int *)(fn + 1) = (int)(fn_stub - fn - CODESIZE_MIN);\
        //CACHEFLUSH((char *)fn, CODESIZE);

Looking into code, there is more statements suffering from this, e.g. *(long long *)(fn + 2) = (long long)fn_stub;\ in the same file.

For a solution, I am thinking that std::copy or memcpy should solve this, but it feels more clumsy than the current code and it may need helper variable.

coolxv commented 2 years ago

@jiridanek

    //5 byte(jmp rel32)
    #define REPLACE_NEAR(t, fn, fn_stub)\
        *fn = 0xE9;\
        int an = (int)(fn_stub - fn - CODESIZE_MIN);\
        *(fn + 1) = ((char*)&an)[0];\
        *(fn + 2) = ((char*)&an)[1];\
        *(fn + 3) = ((char*)&an)[2];\
        *(fn + 4) = ((char*)&an)[3];\
        //CACHEFLUSH((char *)fn, CODESIZE);