diff options
author | Brad King <brad.king@kitware.com> | 2017-01-11 14:58:55 (GMT) |
---|---|---|
committer | CMake Topic Stage <kwrobot@kitware.com> | 2017-01-11 14:58:55 (GMT) |
commit | 12d5ccd10a451301bf3cbdefe8fde744bf6c9467 (patch) | |
tree | fd9ac2a5e522207f547706e0893c0ff78612ecc5 | |
parent | 9a670222758bff23645df36a5cb9d98cb1bafa8e (diff) | |
parent | e537bd91129fc1616f787b64024f1b08d0f7ae45 (diff) | |
download | CMake-12d5ccd10a451301bf3cbdefe8fde744bf6c9467.zip CMake-12d5ccd10a451301bf3cbdefe8fde744bf6c9467.tar.gz CMake-12d5ccd10a451301bf3cbdefe8fde744bf6c9467.tar.bz2 |
Merge topic 'ctest_memcheck-leak_sanitizer'
e537bd91 ctest_memcheck: do not add detect_leaks=1 to ASAN_OPTIONS
0a2e5885 ctest_memcheck: join *SAN_OPTIONS with :
cdacfbd2 MEMORYCHECK_SUPPRESSIONS_FILE: add support for sanitizers
cf590c12 ctest_memcheck: add support for standalone LeakSanitizer
10 files changed, 130 insertions, 22 deletions
diff --git a/Help/release/dev/ctest_memcheck-leak_sanitizer.rst b/Help/release/dev/ctest_memcheck-leak_sanitizer.rst new file mode 100644 index 0000000..3fa5c49 --- /dev/null +++ b/Help/release/dev/ctest_memcheck-leak_sanitizer.rst @@ -0,0 +1,19 @@ +ctest_memcheck-leak_sanitizer +============================= + +* The :command:`ctest_memcheck` command learned to support ``LeakSanitizer`` + independently from ``AddressSanitizer``. + +* The :command:`ctest_memcheck` command no longer automatically adds + ``leak_check=1`` to the options used by ``AddressSanitizer``. The default + behavior of ``AddressSanitizer`` is to run `LeakSanitizer` to check leaks + unless ``leak_check=0``. + +* The :command:`ctest_memcheck` command learned to read the location of + suppressions files for sanitizers from the + :variable:`CTEST_MEMORYCHECK_SUPPRESSIONS_FILE` variable. + +* The :command:`ctest_memcheck` command was fixed to correctly append extra + sanitizer options read from the + :variable:`CTEST_MEMORYCHECK_SANITIZER_OPTIONS` variable to the environment + variables used internally by the sanitizers. diff --git a/Help/variable/CTEST_MEMORYCHECK_TYPE.rst b/Help/variable/CTEST_MEMORYCHECK_TYPE.rst index b963293..b8b4c30 100644 --- a/Help/variable/CTEST_MEMORYCHECK_TYPE.rst +++ b/Help/variable/CTEST_MEMORYCHECK_TYPE.rst @@ -4,5 +4,5 @@ CTEST_MEMORYCHECK_TYPE Specify the CTest ``MemoryCheckType`` setting in a :manual:`ctest(1)` dashboard client script. Valid values are ``Valgrind``, ``Purify``, ``BoundsChecker``, and -``ThreadSanitizer``, ``AddressSanitizer``, ``MemorySanitizer``, and +``ThreadSanitizer``, ``AddressSanitizer``, ``LeakSanitizer``, ``MemorySanitizer``, and ``UndefinedBehaviorSanitizer``. diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index 2c31f60..4d23e45 100644 --- a/Source/CTest/cmCTestMemCheckHandler.cxx +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -305,6 +305,9 @@ void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml) case cmCTestMemCheckHandler::ADDRESS_SANITIZER: xml.Attribute("Checker", "AddressSanitizer"); break; + case cmCTestMemCheckHandler::LEAK_SANITIZER: + xml.Attribute("Checker", "LeakSanitizer"); + break; case cmCTestMemCheckHandler::THREAD_SANITIZER: xml.Attribute("Checker", "ThreadSanitizer"); break; @@ -459,6 +462,12 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() this->LogWithPID = true; // even if we give the log file the pid is added } if (this->CTest->GetCTestConfiguration("MemoryCheckType") == + "LeakSanitizer") { + this->MemoryTester = this->CTest->GetCTestConfiguration("CMakeCommand"); + this->MemoryTesterStyle = cmCTestMemCheckHandler::LEAK_SANITIZER; + this->LogWithPID = true; // even if we give the log file the pid is added + } + if (this->CTest->GetCTestConfiguration("MemoryCheckType") == "ThreadSanitizer") { this->MemoryTester = this->CTest->GetCTestConfiguration("CMakeCommand"); this->MemoryTesterStyle = cmCTestMemCheckHandler::THREAD_SANITIZER; @@ -586,6 +595,7 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() } // these are almost the same but the env var used is different case cmCTestMemCheckHandler::ADDRESS_SANITIZER: + case cmCTestMemCheckHandler::LEAK_SANITIZER: case cmCTestMemCheckHandler::THREAD_SANITIZER: case cmCTestMemCheckHandler::MEMORY_SANITIZER: case cmCTestMemCheckHandler::UB_SANITIZER: { @@ -597,12 +607,20 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() this->MemoryTesterDynamicOptions.push_back("-E"); this->MemoryTesterDynamicOptions.push_back("env"); std::string envVar; - std::string extraOptions = + std::string extraOptions = ":" + this->CTest->GetCTestConfiguration("MemoryCheckSanitizerOptions"); + std::string suppressionsOption; + if (!this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile") + .empty()) { + suppressionsOption = ":suppressions=" + + this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile"); + } if (this->MemoryTesterStyle == cmCTestMemCheckHandler::ADDRESS_SANITIZER) { envVar = "ASAN_OPTIONS"; - extraOptions += " detect_leaks=1"; + } else if (this->MemoryTesterStyle == + cmCTestMemCheckHandler::LEAK_SANITIZER) { + envVar = "LSAN_OPTIONS"; } else if (this->MemoryTesterStyle == cmCTestMemCheckHandler::THREAD_SANITIZER) { envVar = "TSAN_OPTIONS"; @@ -614,8 +632,9 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() envVar = "UBSAN_OPTIONS"; } std::string outputFile = - envVar + "=log_path=\"" + this->MemoryTesterOutputFile + "\" "; - this->MemoryTesterEnvironmentVariable = outputFile + extraOptions; + envVar + "=log_path=\"" + this->MemoryTesterOutputFile + "\""; + this->MemoryTesterEnvironmentVariable = + outputFile + extraOptions + suppressionsOption; break; } default: @@ -644,6 +663,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckOutput(const std::string& str, case cmCTestMemCheckHandler::PURIFY: return this->ProcessMemCheckPurifyOutput(str, log, results); case cmCTestMemCheckHandler::ADDRESS_SANITIZER: + case cmCTestMemCheckHandler::LEAK_SANITIZER: case cmCTestMemCheckHandler::THREAD_SANITIZER: case cmCTestMemCheckHandler::MEMORY_SANITIZER: case cmCTestMemCheckHandler::UB_SANITIZER: @@ -680,6 +700,9 @@ bool cmCTestMemCheckHandler::ProcessMemCheckSanitizerOutput( case cmCTestMemCheckHandler::ADDRESS_SANITIZER: regex = "ERROR: AddressSanitizer: (.*) on.*"; break; + case cmCTestMemCheckHandler::LEAK_SANITIZER: + // use leakWarning regex + break; case cmCTestMemCheckHandler::THREAD_SANITIZER: regex = "WARNING: ThreadSanitizer: (.*) \\(pid=.*\\)"; break; diff --git a/Source/CTest/cmCTestMemCheckHandler.h b/Source/CTest/cmCTestMemCheckHandler.h index 5faace0..ff8b593 100644 --- a/Source/CTest/cmCTestMemCheckHandler.h +++ b/Source/CTest/cmCTestMemCheckHandler.h @@ -47,6 +47,7 @@ private: BOUNDS_CHECKER, // checkers after here do not use the standard error list ADDRESS_SANITIZER, + LEAK_SANITIZER, THREAD_SANITIZER, MEMORY_SANITIZER, UB_SANITIZER diff --git a/Tests/RunCMake/ctest_memcheck/DummyAddressLeakSanitizer-result.txt b/Tests/RunCMake/ctest_memcheck/DummyAddressLeakSanitizer-result.txt new file mode 100644 index 0000000..b57e2de --- /dev/null +++ b/Tests/RunCMake/ctest_memcheck/DummyAddressLeakSanitizer-result.txt @@ -0,0 +1 @@ +(-1|255) diff --git a/Tests/RunCMake/ctest_memcheck/DummyAddressLeakSanitizer-stderr.txt b/Tests/RunCMake/ctest_memcheck/DummyAddressLeakSanitizer-stderr.txt new file mode 100644 index 0000000..327bd5c --- /dev/null +++ b/Tests/RunCMake/ctest_memcheck/DummyAddressLeakSanitizer-stderr.txt @@ -0,0 +1 @@ +Cannot find memory tester output file: .*/Tests/RunCMake/ctest_memcheck/DummyAddressLeakSanitizer-build/Testing/Temporary/MemoryChecker.1.log\.\* diff --git a/Tests/RunCMake/ctest_memcheck/DummyAddressLeakSanitizer-stdout.txt b/Tests/RunCMake/ctest_memcheck/DummyAddressLeakSanitizer-stdout.txt new file mode 100644 index 0000000..97a8a9b --- /dev/null +++ b/Tests/RunCMake/ctest_memcheck/DummyAddressLeakSanitizer-stdout.txt @@ -0,0 +1,3 @@ +Memory checking results: +Direct leak - 2 +Indirect leak - 1 diff --git a/Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake b/Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake index 212bfdb..352a381 100644 --- a/Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake +++ b/Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake @@ -30,22 +30,22 @@ unset(CMAKELISTS_EXTRA_CODE) unset(CTEST_EXTRA_CODE) #----------------------------------------------------------------------------- -# add LeakSanitizer test +# add standalone LeakSanitizer test set(CTEST_EXTRA_CODE -"set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS \"simulate_sanitizer=1 report_bugs=1 history_size=5 exitcode=55\") +"set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS \"simulate_sanitizer=1:report_bugs=1:history_size=5:exitcode=55\") ") set(CMAKELISTS_EXTRA_CODE "add_test(NAME TestSan COMMAND \"${CMAKE_COMMAND}\" -P \"${RunCMake_SOURCE_DIR}/testLeakSanitizer.cmake\") ") -run_mc_test(DummyLeakSanitizer "" -DMEMCHECK_TYPE=AddressSanitizer) +run_mc_test(DummyLeakSanitizer "" -DMEMCHECK_TYPE=LeakSanitizer) unset(CMAKELISTS_EXTRA_CODE) unset(CTEST_EXTRA_CODE) #----------------------------------------------------------------------------- # add AddressSanitizer test set(CTEST_EXTRA_CODE -"set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS \"simulate_sanitizer=1 report_bugs=1 history_size=5 exitcode=55\") +"set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS \"simulate_sanitizer=1:report_bugs=1:history_size=5:exitcode=55\") ") set(CMAKELISTS_EXTRA_CODE "add_test(NAME TestSan COMMAND \"\${CMAKE_COMMAND}\" @@ -56,9 +56,22 @@ unset(CMAKELISTS_EXTRA_CODE) unset(CTEST_EXTRA_CODE) #----------------------------------------------------------------------------- +# add AddressSanitizer/LeakSanitizer test +set(CTEST_EXTRA_CODE +"set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS \"simulate_sanitizer=1:report_bugs=1:history_size=5:exitcode=55\") +") +set(CMAKELISTS_EXTRA_CODE +"add_test(NAME TestSan COMMAND \"${CMAKE_COMMAND}\" +-P \"${RunCMake_SOURCE_DIR}/testAddressLeakSanitizer.cmake\") +") +run_mc_test(DummyAddressLeakSanitizer "" -DMEMCHECK_TYPE=AddressSanitizer) +unset(CMAKELISTS_EXTRA_CODE) +unset(CTEST_EXTRA_CODE) + +#----------------------------------------------------------------------------- # add MemorySanitizer test set(CTEST_EXTRA_CODE -"set(CTEST_MEMORYCHECK_COMMAND_OPTIONS \"simulate_sanitizer=1 report_bugs=1 history_size=5 exitcode=55\") +"set(CTEST_MEMORYCHECK_COMMAND_OPTIONS \"simulate_sanitizer=1:report_bugs=1:history_size=5:exitcode=55\") ") set(CMAKELISTS_EXTRA_CODE "add_test(NAME TestSan COMMAND \"\${CMAKE_COMMAND}\" @@ -151,13 +164,13 @@ unset(CTEST_SUFFIX_CODE) set(CTEST_SUFFIX_CODE "message(\"Defect count: \${defect_count}\")") set(CTEST_MEMCHECK_ARGS "DEFECT_COUNT defect_count") set(CTEST_EXTRA_CODE -"set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS \"simulate_sanitizer=1 report_bugs=1 history_size=5 exitcode=55\") +"set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS \"simulate_sanitizer=1:report_bugs=1:history_size=5:exitcode=55\") ") set(CMAKELISTS_EXTRA_CODE "add_test(NAME TestSan COMMAND \"${CMAKE_COMMAND}\" -P \"${RunCMake_SOURCE_DIR}/testLeakSanitizer.cmake\") ") -run_mc_test(DummyLeakSanitizerPrintDefects "" -DMEMCHECK_TYPE=AddressSanitizer) +run_mc_test(DummyLeakSanitizerPrintDefects "" -DMEMCHECK_TYPE=LeakSanitizer) unset(CMAKELISTS_EXTRA_CODE) unset(CTEST_EXTRA_CODE) unset(CTEST_MEMCHECK_ARGS) diff --git a/Tests/RunCMake/ctest_memcheck/testAddressLeakSanitizer.cmake b/Tests/RunCMake/ctest_memcheck/testAddressLeakSanitizer.cmake new file mode 100644 index 0000000..2a57b11 --- /dev/null +++ b/Tests/RunCMake/ctest_memcheck/testAddressLeakSanitizer.cmake @@ -0,0 +1,47 @@ +# this file simulates a program that has been built with AddressSanitizer +# options + +message("ASAN_OPTIONS = [$ENV{ASAN_OPTIONS}]") +string(REGEX REPLACE ".*log_path=\"([^\"]*)\".*" "\\1" LOG_FILE "$ENV{ASAN_OPTIONS}") +message("LOG_FILE=[${LOG_FILE}]") + +# if we are not asked to simulate AddressSanitizer don't do it +if(NOT "$ENV{ASAN_OPTIONS}]" MATCHES "simulate_sanitizer.1") + return() +endif() + +# clear the log files +file(REMOVE "${LOG_FILE}.2343") +file(REMOVE "${LOG_FILE}.2344") + +# create an error of each type of LeakSanitizer + +file(APPEND "${LOG_FILE}.2343" +"================================================================= +==25308==ERROR: LeakSanitizer: detected memory leaks + +Direct leak of 4360 byte(s) in 1 object(s) allocated from: + #0 0x46c669 in operator new[](unsigned long) (/home/kitware/msan/a.out+0x46c669) + #1 0x4823b4 in main /home/kitware/msan/memcheck.cxx:12 + #2 0x7fa72bee476c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226 + +SUMMARY: AddressSanitizer: 4436 byte(s) leaked in 2 allocation(s). +") +file(APPEND "${LOG_FILE}.2342" +"================================================================= +==25308==ERROR: LeakSanitizer: detected memory leaks + +Direct leak of 76 byte(s) in 1 object(s) allocated from: + #0 0x46c669 in operator new[](unsigned long) (/home/kitware/msan/a.out+0x46c669) + #1 0x4821b8 in foo() /home/kitware/msan/memcheck.cxx:4 + #2 0x4823f2 in main /home/kitware/msan/memcheck.cxx:14 + #3 0x7fa72bee476c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226 + +Indirect leak of 76 byte(s) in 1 object(s) allocated from: + #0 0x46c669 in operator new[](unsigned long) (/home/kitware/msan/a.out+0x46c669) + #1 0x4821b8 in foo() /home/kitware/msan/memcheck.cxx:4 + #2 0x4823f2 in main /home/kitware/msan/memcheck.cxx:14 + #3 0x7fa72bee476c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226 + +SUMMARY: AddressSanitizer: 4436 byte(s) leaked in 2 allocation(s). +") diff --git a/Tests/RunCMake/ctest_memcheck/testLeakSanitizer.cmake b/Tests/RunCMake/ctest_memcheck/testLeakSanitizer.cmake index 02030be..af214c8 100644 --- a/Tests/RunCMake/ctest_memcheck/testLeakSanitizer.cmake +++ b/Tests/RunCMake/ctest_memcheck/testLeakSanitizer.cmake @@ -1,20 +1,20 @@ -# this file simulates a program that has been built with thread sanitizer +# this file simulates a program that has been built with LeakSanitizer # options -message("ASAN_OPTIONS = [$ENV{ASAN_OPTIONS}]") -string(REGEX REPLACE ".*log_path=\"([^\"]*)\".*" "\\1" LOG_FILE "$ENV{ASAN_OPTIONS}") +message("LSAN_OPTIONS = [$ENV{LSAN_OPTIONS}]") +string(REGEX REPLACE ".*log_path=\"([^\"]*)\".*" "\\1" LOG_FILE "$ENV{LSAN_OPTIONS}") message("LOG_FILE=[${LOG_FILE}]") -# if we are not asked to simulate leak sanitizer don't do it -if(NOT "$ENV{ASAN_OPTIONS}]" MATCHES "simulate_sanitizer.1") + +# if we are not asked to simulate LeakSanitizer don't do it +if(NOT "$ENV{LSAN_OPTIONS}]" MATCHES "simulate_sanitizer.1") return() endif() -# clear the log file +# clear the log files file(REMOVE "${LOG_FILE}.2343") file(REMOVE "${LOG_FILE}.2344") -# create an error of each type of thread santizer -# these names come from tsan_report.cc in llvm +# create an error of each type of LeakSanitizer file(APPEND "${LOG_FILE}.2343" "================================================================= @@ -25,7 +25,7 @@ Direct leak of 4360 byte(s) in 1 object(s) allocated from: #1 0x4823b4 in main /home/kitware/msan/memcheck.cxx:12 #2 0x7fa72bee476c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226 -SUMMARY: AddressSanitizer: 4436 byte(s) leaked in 2 allocation(s). +SUMMARY: LeakSanitizer: 4436 byte(s) leaked in 2 allocation(s). ") file(APPEND "${LOG_FILE}.2342" "================================================================= @@ -43,5 +43,5 @@ Indirect leak of 76 byte(s) in 1 object(s) allocated from: #2 0x4823f2 in main /home/kitware/msan/memcheck.cxx:14 #3 0x7fa72bee476c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226 -SUMMARY: AddressSanitizer: 4436 byte(s) leaked in 2 allocation(s). +SUMMARY: LeakSanitizer: 4436 byte(s) leaked in 2 allocation(s). ") |