diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index dfa2533..a97157c 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -63,13 +63,24 @@ jobs: label: "relwithdebinfo_gcc13", run_mtr: true } + - { + name: "GCC 13 ASan", + build_type: "Debug", + cc: "gcc-13", + cxx: "g++-13", + sanitizer_cmake_flags: "-DWITH_ASAN=ON", + label: "asan_gcc13", + run_mtr: true, + mtr_options: "--sanitize" + } - { name: "Clang 17 Debug", build_type: "Debug", cc: "clang-17", cxx: "clang++-17", libcxx_cmake_flags: "-DWITH_STDLIB_LIBCXX=ON", - label: "debug_clang17" + label: "debug_clang17", + run_clang_tidy: true, } - { name: "Clang 17 RelWithDebInfo", @@ -77,7 +88,19 @@ jobs: cc: "clang-17", cxx: "clang++-17", libcxx_cmake_flags: "-DWITH_STDLIB_LIBCXX=ON", - label: "relwithdebinfo_clang17" + label: "relwithdebinfo_clang17", + run_clang_tidy: true, + } + - { + name: "Clang 17 ASan", + build_type: "Debug", + cc: "clang-17", + cxx: "clang++-17", + libcxx_cmake_flags: "-DWITH_STDLIB_LIBCXX=ON", + sanitizer_cmake_flags: "-DWITH_ASAN=ON", + label: "asan_clang17", + run_mtr: true, + mtr_options: "--sanitize" } steps: @@ -96,6 +119,7 @@ jobs: - name: Install MySQL client libraries run: | + sudo apt-get update sudo apt-get install libmysqlclient-dev - name: Install MySQL server and MTR @@ -155,6 +179,7 @@ jobs: -DCMAKE_C_COMPILER=${{matrix.config.cc}} \ -DCMAKE_CXX_COMPILER=${{matrix.config.cxx}} \ ${{matrix.config.libcxx_cmake_flags}} \ + ${{matrix.config.sanitizer_cmake_flags}} \ -DBoost_ROOT=${{runner.temp}}/deps/${{format('boost_{0}_{1}_{2}', env.BOOST_MAJOR, env.BOOST_MINOR, env.BOOST_PATCH)}} \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON @@ -166,11 +191,11 @@ jobs: run: cmake --build ${{github.workspace}}/../build-${{matrix.config.label}} --config ${{matrix.config.build_type}} --parallel - name: Info Clang Tidy - if: startsWith(matrix.config.name, 'Clang') + if: matrix.config.run_clang_tidy run: clang-tidy-17 --version - name: Clang Tidy - if: startsWith(matrix.config.name, 'Clang') + if: matrix.config.run_clang_tidy # Run Clang Tidy run: run-clang-tidy-17 -header-filter=.* -j=${{steps.cpu-cores.outputs.count}} -use-color -p=${{github.workspace}}/../build-${{matrix.config.label}} @@ -186,7 +211,7 @@ jobs: BINSRV=${{github.workspace}}/../build-${{matrix.config.label}}/binlog_server ./mtr \ --client-bindir=/usr/lib/mysql-test/bin --vardir=${{github.workspace}}/../mtrvardir \ --force --max-test-fail=0 --retry=0 --nounit-tests --big-test --repeat=2 --parallel=${{steps.cpu-cores.outputs.count}} \ - --suite=binlog_streaming + --suite=binlog_streaming ${{matrix.config.mtr_options}} - name: CTest working-directory: ${{github.workspace}}/../build-${{matrix.config.label}} diff --git a/CMakeLists.txt b/CMakeLists.txt index 2281ae5..07fd8b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,6 +44,19 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") ) endif() +option(WITH_ASAN "Enable Address Sanitizer" OFF) +if(WITH_ASAN) + # By default during the build time, on both GCC anf Clang, LeakSanitized is + # enabled by default when AddressSanitizer is enabled. However, in runtime + # it is enabled by default only on Linux platforms. Therefore, on MacOS, + # the executable needs to be run with 'ASAN_OPTIONS=detect_leaks=1'. + # Also AddressSanitizerUseAfterScope is also enabled by default both during + # the build time and in runtime, so there is no need to specify + # '-fsanitize-address-use-after-scope' explicitly or modify 'ASAN_OPTIONS' + target_compile_options(binlog_server_compiler_flags INTERFACE "-fsanitize=address") + target_link_options(binlog_server_compiler_flags INTERFACE "-fsanitize=address") +endif() + find_package(Boost 1.83.0 EXACT REQUIRED) find_package(MySQL REQUIRED) diff --git a/mtr/binlog_streaming/t/binsrv.test b/mtr/binlog_streaming/t/binsrv.test index a7cdaee..16cd21c 100644 --- a/mtr/binlog_streaming/t/binsrv.test +++ b/mtr/binlog_streaming/t/binsrv.test @@ -95,7 +95,7 @@ if ($have_windows) { --echo *** Executing the Binlog Server utility to download all binlog data --echo *** from the server to the directory (second --echo *** binlog is still open / in use). ---exec $BINSRV $binsrv_config_file_path > /dev/null 2>&1 +--exec $BINSRV $binsrv_config_file_path > /dev/null # At this point we have 2 binlog files $first_binlog (already closed/rotedted # by the server) and $second_binlog (currently open). @@ -158,7 +158,7 @@ FLUSH BINARY LOGS; --echo *** Executing the Binlog Server utility one more time (the second --echo *** binlog is no longer open / in use). Here we should also continue --echo *** streaming binlog events from the last saved position. ---exec $BINSRV $binsrv_config_file_path > /dev/null 2>&1 +--exec $BINSRV $binsrv_config_file_path > /dev/null --echo --echo *** Comparing server and downloaded versions of the first binlog file diff --git a/src/app.cpp b/src/app.cpp index 06fe13c..624ed39 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -133,6 +133,24 @@ void receive_binlog_events(binsrv::basic_logger &logger, } // anonymous namespace int main(int argc, char *argv[]) { + /* + std::string *s_ptr{nullptr}; + { + auto ptr{std::make_unique(128, 'x')}; + s_ptr = ptr.get(); + } + s_ptr->clear(); + */ + static constexpr std::size_t big_enough{128U}; + volatile bool delete_flag{true}; + auto deleter{[&delete_flag](void *ptr) { + if (delete_flag) + std::free(ptr); + }}; + std::unique_ptr ptr{std::malloc(big_enough), + deleter}; + delete_flag = false; + using namespace std::string_literals; int exit_code = EXIT_FAILURE; @@ -143,10 +161,11 @@ int main(int argc, char *argv[]) { if (number_of_cmd_args != binsrv::main_config::flattened_size + 1 && number_of_cmd_args != 2) { - std::cerr - << "usage: " << executable_name - << " \n" - << " " << executable_name << " \n"; + std::cerr << "usage: " << executable_name + << " " + " " + " \n" + << " " << executable_name << " \n"; return exit_code; } binsrv::basic_logger_ptr logger;