Merge topic 'thread-sanitizer'
1e005ead
CTest: Fix MemoryCheckType from 'ctest -T MemCheck'44726714
ctest_memcheck: Add support for memory and leak sanitizer.
This commit is contained in:
commit
66e88af6d0
|
@ -71,6 +71,7 @@ Compiler: @CMAKE_CXX_COMPILER@
|
||||||
PurifyCommand: @PURIFYCOMMAND@
|
PurifyCommand: @PURIFYCOMMAND@
|
||||||
ValgrindCommand: @VALGRIND_COMMAND@
|
ValgrindCommand: @VALGRIND_COMMAND@
|
||||||
ValgrindCommandOptions: @VALGRIND_COMMAND_OPTIONS@
|
ValgrindCommandOptions: @VALGRIND_COMMAND_OPTIONS@
|
||||||
|
MemoryCheckType: @MEMORYCHECK_TYPE@
|
||||||
MemoryCheckCommand: @MEMORYCHECK_COMMAND@
|
MemoryCheckCommand: @MEMORYCHECK_COMMAND@
|
||||||
MemoryCheckCommandOptions: @MEMORYCHECK_COMMAND_OPTIONS@
|
MemoryCheckCommandOptions: @MEMORYCHECK_COMMAND_OPTIONS@
|
||||||
MemoryCheckSuppressionFile: @MEMORYCHECK_SUPPRESSIONS_FILE@
|
MemoryCheckSuppressionFile: @MEMORYCHECK_SUPPRESSIONS_FILE@
|
||||||
|
|
|
@ -45,11 +45,23 @@ static CatToErrorType cmCTestMemCheckBoundsChecker[] = {
|
||||||
{0,0}
|
{0,0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void xmlReportError(int line, const char* msg, void* data)
|
||||||
|
{
|
||||||
|
cmCTest* ctest = (cmCTest*)data;
|
||||||
|
cmCTestLog(ctest, ERROR_MESSAGE,
|
||||||
|
"Error parsing XML in stream at line "
|
||||||
|
<< line << ": " << msg << std::endl);
|
||||||
|
}
|
||||||
|
|
||||||
// parse the xml file containing the results of last BoundsChecker run
|
// parse the xml file containing the results of last BoundsChecker run
|
||||||
class cmBoundsCheckerParser : public cmXMLParser
|
class cmBoundsCheckerParser : public cmXMLParser
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
cmBoundsCheckerParser(cmCTest* c) { this->CTest = c;}
|
cmBoundsCheckerParser(cmCTest* c)
|
||||||
|
{
|
||||||
|
this->CTest = c;
|
||||||
|
this->SetErrorCallback(xmlReportError, (void*)c);
|
||||||
|
}
|
||||||
void StartElement(const std::string& name, const char** atts)
|
void StartElement(const std::string& name, const char** atts)
|
||||||
{
|
{
|
||||||
if(name == "MemoryLeak" ||
|
if(name == "MemoryLeak" ||
|
||||||
|
@ -334,8 +346,8 @@ void cmCTestMemCheckHandler::PopulateCustomVectors(cmMakefile *mf)
|
||||||
this->CTest->PopulateCustomVector(mf,
|
this->CTest->PopulateCustomVector(mf,
|
||||||
"CTEST_CUSTOM_MEMCHECK_IGNORE",
|
"CTEST_CUSTOM_MEMCHECK_IGNORE",
|
||||||
this->CustomTestsIgnore);
|
this->CustomTestsIgnore);
|
||||||
this->CTest->SetCTestConfigurationFromCMakeVariable(
|
std::string cmake = cmSystemTools::GetCMakeCommand();
|
||||||
mf, "CMakeCommand", "CMAKE_COMMAND");
|
this->CTest->SetCTestConfiguration("CMakeCommand", cmake.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
@ -361,6 +373,9 @@ void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os)
|
||||||
case cmCTestMemCheckHandler::THREAD_SANITIZER:
|
case cmCTestMemCheckHandler::THREAD_SANITIZER:
|
||||||
os << "ThreadSanitizer";
|
os << "ThreadSanitizer";
|
||||||
break;
|
break;
|
||||||
|
case cmCTestMemCheckHandler::ADDRESS_SANITIZER:
|
||||||
|
os << "AddressSanitizer";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
os << "Unknown";
|
os << "Unknown";
|
||||||
}
|
}
|
||||||
|
@ -529,6 +544,14 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
|
||||||
this->MemoryTesterStyle = cmCTestMemCheckHandler::THREAD_SANITIZER;
|
this->MemoryTesterStyle = cmCTestMemCheckHandler::THREAD_SANITIZER;
|
||||||
this->LogWithPID = true; // even if we give the log file the pid is added
|
this->LogWithPID = true; // even if we give the log file the pid is added
|
||||||
}
|
}
|
||||||
|
if ( this->CTest->GetCTestConfiguration("MemoryCheckType")
|
||||||
|
== "AddressSanitizer")
|
||||||
|
{
|
||||||
|
this->MemoryTester
|
||||||
|
= this->CTest->GetCTestConfiguration("CMakeCommand").c_str();
|
||||||
|
this->MemoryTesterStyle = cmCTestMemCheckHandler::ADDRESS_SANITIZER;
|
||||||
|
this->LogWithPID = true; // even if we give the log file the pid is added
|
||||||
|
}
|
||||||
// Check the MemoryCheckType
|
// Check the MemoryCheckType
|
||||||
if(this->MemoryTesterStyle == cmCTestMemCheckHandler::UNKNOWN)
|
if(this->MemoryTesterStyle == cmCTestMemCheckHandler::UNKNOWN)
|
||||||
{
|
{
|
||||||
|
@ -651,6 +674,9 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
|
||||||
this->MemoryTesterOptions.push_back("/M");
|
this->MemoryTesterOptions.push_back("/M");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// these two are almost the same but the env var used
|
||||||
|
// is different
|
||||||
|
case cmCTestMemCheckHandler::ADDRESS_SANITIZER:
|
||||||
case cmCTestMemCheckHandler::THREAD_SANITIZER:
|
case cmCTestMemCheckHandler::THREAD_SANITIZER:
|
||||||
{
|
{
|
||||||
// To pass arguments to ThreadSanitizer the environment variable
|
// To pass arguments to ThreadSanitizer the environment variable
|
||||||
|
@ -660,9 +686,16 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
|
||||||
// TSAN_OPTIONS string with the log_path in it.
|
// TSAN_OPTIONS string with the log_path in it.
|
||||||
this->MemoryTesterDynamicOptions.push_back("-E");
|
this->MemoryTesterDynamicOptions.push_back("-E");
|
||||||
this->MemoryTesterDynamicOptions.push_back("env");
|
this->MemoryTesterDynamicOptions.push_back("env");
|
||||||
std::string outputFile = "TSAN_OPTIONS=log_path=\""
|
std::string envVar = "TSAN_OPTIONS";
|
||||||
|
std::string extraOptions;
|
||||||
|
if(this->MemoryTesterStyle == cmCTestMemCheckHandler::ADDRESS_SANITIZER)
|
||||||
|
{
|
||||||
|
envVar = "ASAN_OPTIONS";
|
||||||
|
extraOptions = " detect_leaks=1";
|
||||||
|
}
|
||||||
|
std::string outputFile = envVar + "=log_path=\""
|
||||||
+ this->MemoryTesterOutputFile + "\"";
|
+ this->MemoryTesterOutputFile + "\"";
|
||||||
this->MemoryTesterEnvironmentVariable = outputFile;
|
this->MemoryTesterEnvironmentVariable = outputFile + extraOptions;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -695,9 +728,11 @@ ProcessMemCheckOutput(const std::string& str,
|
||||||
return this->ProcessMemCheckPurifyOutput(str, log, results);
|
return this->ProcessMemCheckPurifyOutput(str, log, results);
|
||||||
}
|
}
|
||||||
else if ( this->MemoryTesterStyle ==
|
else if ( this->MemoryTesterStyle ==
|
||||||
cmCTestMemCheckHandler::THREAD_SANITIZER )
|
cmCTestMemCheckHandler::THREAD_SANITIZER ||
|
||||||
|
this->MemoryTesterStyle ==
|
||||||
|
cmCTestMemCheckHandler::ADDRESS_SANITIZER)
|
||||||
{
|
{
|
||||||
return this->ProcessMemCheckThreadSanitizerOutput(str, log, results);
|
return this->ProcessMemCheckSanitizerOutput(str, log, results);
|
||||||
}
|
}
|
||||||
else if ( this->MemoryTesterStyle ==
|
else if ( this->MemoryTesterStyle ==
|
||||||
cmCTestMemCheckHandler::BOUNDS_CHECKER )
|
cmCTestMemCheckHandler::BOUNDS_CHECKER )
|
||||||
|
@ -730,12 +765,21 @@ std::vector<int>::size_type cmCTestMemCheckHandler::FindOrAddWarning(
|
||||||
return this->ResultStrings.size()-1;
|
return this->ResultStrings.size()-1;
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
bool cmCTestMemCheckHandler::ProcessMemCheckThreadSanitizerOutput(
|
bool cmCTestMemCheckHandler::ProcessMemCheckSanitizerOutput(
|
||||||
const std::string& str, std::string& log,
|
const std::string& str, std::string& log,
|
||||||
std::vector<int>& result)
|
std::vector<int>& result)
|
||||||
{
|
{
|
||||||
cmsys::RegularExpression
|
std::string regex;
|
||||||
sanitizerWarning("WARNING: ThreadSanitizer: (.*) \\(pid=.*\\)");
|
if(this->MemoryTesterStyle == cmCTestMemCheckHandler::THREAD_SANITIZER)
|
||||||
|
{
|
||||||
|
regex = "WARNING: ThreadSanitizer: (.*) \\(pid=.*\\)";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
regex = "ERROR: AddressSanitizer: (.*) on.*";
|
||||||
|
}
|
||||||
|
cmsys::RegularExpression sanitizerWarning(regex);
|
||||||
|
cmsys::RegularExpression leakWarning("(Direct|Indirect) leak of .*");
|
||||||
int defects = 0;
|
int defects = 0;
|
||||||
std::vector<std::string> lines;
|
std::vector<std::string> lines;
|
||||||
cmSystemTools::Split(str.c_str(), lines);
|
cmSystemTools::Split(str.c_str(), lines);
|
||||||
|
@ -744,10 +788,18 @@ bool cmCTestMemCheckHandler::ProcessMemCheckThreadSanitizerOutput(
|
||||||
for( std::vector<std::string>::iterator i = lines.begin();
|
for( std::vector<std::string>::iterator i = lines.begin();
|
||||||
i != lines.end(); ++i)
|
i != lines.end(); ++i)
|
||||||
{
|
{
|
||||||
if(sanitizerWarning.find(*i))
|
std::string resultFound;
|
||||||
|
if(leakWarning.find(*i))
|
||||||
{
|
{
|
||||||
std::string warning = sanitizerWarning.match(1);
|
resultFound = leakWarning.match(1)+" leak";
|
||||||
std::vector<int>::size_type idx = this->FindOrAddWarning(warning);
|
}
|
||||||
|
else if (sanitizerWarning.find(*i))
|
||||||
|
{
|
||||||
|
resultFound = sanitizerWarning.match(1);
|
||||||
|
}
|
||||||
|
if(resultFound.size())
|
||||||
|
{
|
||||||
|
std::vector<int>::size_type idx = this->FindOrAddWarning(resultFound);
|
||||||
if(result.size() == 0 || idx > result.size()-1)
|
if(result.size() == 0 || idx > result.size()-1)
|
||||||
{
|
{
|
||||||
result.push_back(1);
|
result.push_back(1);
|
||||||
|
|
|
@ -50,7 +50,8 @@ private:
|
||||||
PURIFY,
|
PURIFY,
|
||||||
BOUNDS_CHECKER,
|
BOUNDS_CHECKER,
|
||||||
// checkers after hear do not use the standard error list
|
// checkers after hear do not use the standard error list
|
||||||
THREAD_SANITIZER
|
THREAD_SANITIZER,
|
||||||
|
ADDRESS_SANITIZER
|
||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
enum { // Memory faults
|
enum { // Memory faults
|
||||||
|
@ -132,7 +133,7 @@ private:
|
||||||
bool ProcessMemCheckPurifyOutput(const std::string& str,
|
bool ProcessMemCheckPurifyOutput(const std::string& str,
|
||||||
std::string& log,
|
std::string& log,
|
||||||
std::vector<int>& results);
|
std::vector<int>& results);
|
||||||
bool ProcessMemCheckThreadSanitizerOutput(const std::string& str,
|
bool ProcessMemCheckSanitizerOutput(const std::string& str,
|
||||||
std::string& log,
|
std::string& log,
|
||||||
std::vector<int>& results);
|
std::vector<int>& results);
|
||||||
bool ProcessMemCheckBoundsCheckerOutput(const std::string& str,
|
bool ProcessMemCheckBoundsCheckerOutput(const std::string& str,
|
||||||
|
|
|
@ -20,6 +20,8 @@ cmXMLParser::cmXMLParser()
|
||||||
{
|
{
|
||||||
this->Parser = 0;
|
this->Parser = 0;
|
||||||
this->ParseError = 0;
|
this->ParseError = 0;
|
||||||
|
this->ReportCallback = 0;
|
||||||
|
this->ReportCallbackData = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
@ -233,6 +235,13 @@ void cmXMLParser::ReportXmlParseError()
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void cmXMLParser::ReportError(int line, int, const char* msg)
|
void cmXMLParser::ReportError(int line, int, const char* msg)
|
||||||
{
|
{
|
||||||
|
if(this->ReportCallback)
|
||||||
|
{
|
||||||
|
this->ReportCallback(line, msg, this->ReportCallbackData);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
std::cerr << "Error parsing XML in stream at line "
|
std::cerr << "Error parsing XML in stream at line "
|
||||||
<< line << ": " << msg << std::endl;
|
<< line << ": " << msg << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,11 +50,18 @@ public:
|
||||||
virtual int ParseChunk(const char* inputString,
|
virtual int ParseChunk(const char* inputString,
|
||||||
std::string::size_type length);
|
std::string::size_type length);
|
||||||
virtual int CleanupParser();
|
virtual int CleanupParser();
|
||||||
|
typedef void (*ReportFunction)(int, const char*, void*);
|
||||||
|
void SetErrorCallback(ReportFunction f, void* d)
|
||||||
|
{
|
||||||
|
this->ReportCallback = f;
|
||||||
|
this->ReportCallbackData = d;
|
||||||
|
}
|
||||||
protected:
|
protected:
|
||||||
//! This variable is true if there was a parse error while parsing in
|
//! This variable is true if there was a parse error while parsing in
|
||||||
//chunks.
|
//chunks.
|
||||||
int ParseError;
|
int ParseError;
|
||||||
|
ReportFunction ReportCallback;
|
||||||
|
void* ReportCallbackData;
|
||||||
|
|
||||||
//1 Expat parser structure. Exists only during call to Parse().
|
//1 Expat parser structure. Exists only during call to Parse().
|
||||||
void* Parser;
|
void* Parser;
|
||||||
|
|
|
@ -113,9 +113,44 @@ set(CMAKELISTS_EXTRA_CODE
|
||||||
-P \"${CMAKE_CURRENT_SOURCE_DIR}/testThreadSanitizer.cmake\")
|
-P \"${CMAKE_CURRENT_SOURCE_DIR}/testThreadSanitizer.cmake\")
|
||||||
")
|
")
|
||||||
gen_mc_test_internal(DummyThreadSanitizer "" -DMEMCHECK_TYPE=ThreadSanitizer)
|
gen_mc_test_internal(DummyThreadSanitizer "" -DMEMCHECK_TYPE=ThreadSanitizer)
|
||||||
|
set_tests_properties(CTestTestMemcheckDummyThreadSanitizer PROPERTIES
|
||||||
|
PASS_REGULAR_EXPRESSION
|
||||||
|
".*Memory checking results:.*data race.* - 1.*data race on vptr .ctor/dtor vs virtual call. - 1.*heap-use-after-free - 1.*thread leak - 1.*destroy of a locked mutex - 1.*double lock of a mutex - 1.*unlock of an unlocked mutex .or by a wrong thread. - 1.*read lock of a write locked mutex - 1.*read unlock of a write locked mutex - 1.*signal-unsafe call inside of a signal - 1.*signal handler spoils errno - 1.*lock-order-inversion .potential deadlock. - 1.*")
|
||||||
set(CMAKELISTS_EXTRA_CODE )
|
set(CMAKELISTS_EXTRA_CODE )
|
||||||
set(CTEST_EXTRA_CODE)
|
set(CTEST_EXTRA_CODE)
|
||||||
|
|
||||||
|
# add LeakSanitizer test
|
||||||
|
set(CTEST_EXTRA_CODE
|
||||||
|
"set(CTEST_MEMORYCHECK_COMMAND_OPTIONS \"report_bugs=1 history_size=5 exitcode=55\")
|
||||||
|
")
|
||||||
|
|
||||||
|
set(CMAKELISTS_EXTRA_CODE
|
||||||
|
"add_test(NAME TestSan COMMAND \"${CMAKE_COMMAND}\"
|
||||||
|
-P \"${CMAKE_CURRENT_SOURCE_DIR}/testLeakSanitizer.cmake\")
|
||||||
|
")
|
||||||
|
gen_mc_test_internal(DummyLeakSanitizer "" -DMEMCHECK_TYPE=AddressSanitizer)
|
||||||
|
set(CMAKELISTS_EXTRA_CODE )
|
||||||
|
set(CTEST_EXTRA_CODE)
|
||||||
|
set_tests_properties(CTestTestMemcheckDummyLeakSanitizer PROPERTIES
|
||||||
|
PASS_REGULAR_EXPRESSION
|
||||||
|
".*Memory checking results:.*Direct leak - 2.*Indirect leak - 1.*")
|
||||||
|
# add AddressSanitizer test
|
||||||
|
set(CTEST_EXTRA_CODE
|
||||||
|
"set(CTEST_MEMORYCHECK_COMMAND_OPTIONS \"report_bugs=1 history_size=5 exitcode=55\")
|
||||||
|
")
|
||||||
|
|
||||||
|
set(CMAKELISTS_EXTRA_CODE
|
||||||
|
"add_test(NAME TestSan COMMAND \"${CMAKE_COMMAND}\"
|
||||||
|
-P \"${CMAKE_CURRENT_SOURCE_DIR}/testAddressSanitizer.cmake\")
|
||||||
|
")
|
||||||
|
gen_mc_test_internal(DummyAddressSanitizer "" -DMEMCHECK_TYPE=AddressSanitizer)
|
||||||
|
set(CMAKELISTS_EXTRA_CODE )
|
||||||
|
set(CTEST_EXTRA_CODE)
|
||||||
|
set_tests_properties(CTestTestMemcheckDummyAddressSanitizer PROPERTIES
|
||||||
|
PASS_REGULAR_EXPRESSION
|
||||||
|
".*Memory checking results:.*heap-buffer-overflow - 1.*")
|
||||||
|
|
||||||
|
|
||||||
gen_mc_test(DummyPurify "\${PSEUDO_PURIFY}")
|
gen_mc_test(DummyPurify "\${PSEUDO_PURIFY}")
|
||||||
gen_mc_test(DummyValgrind "\${PSEUDO_VALGRIND}")
|
gen_mc_test(DummyValgrind "\${PSEUDO_VALGRIND}")
|
||||||
gen_mc_test(DummyBC "\${PSEUDO_BC}")
|
gen_mc_test(DummyBC "\${PSEUDO_BC}")
|
||||||
|
@ -202,10 +237,6 @@ set_tests_properties(CTestTestMemcheckDummyValgrindTwoTargets PROPERTIES
|
||||||
PASS_REGULAR_EXPRESSION
|
PASS_REGULAR_EXPRESSION
|
||||||
"\nMemory check project ${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/DummyValgrindTwoTargets\n.*\n *Start 1: RunCMake\n(.*\n)?Memory check command: .* \"--log-file=${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/DummyValgrindTwoTargets/Testing/Temporary/MemoryChecker.1.log\" \"-q\".*\n *Start 2: RunCMakeAgain\n(.*\n)?Memory check command: .* \"--log-file=${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/DummyValgrindTwoTargets/Testing/Temporary/MemoryChecker.2.log\" \"-q\".*\n")
|
"\nMemory check project ${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/DummyValgrindTwoTargets\n.*\n *Start 1: RunCMake\n(.*\n)?Memory check command: .* \"--log-file=${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/DummyValgrindTwoTargets/Testing/Temporary/MemoryChecker.1.log\" \"-q\".*\n *Start 2: RunCMakeAgain\n(.*\n)?Memory check command: .* \"--log-file=${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/DummyValgrindTwoTargets/Testing/Temporary/MemoryChecker.2.log\" \"-q\".*\n")
|
||||||
|
|
||||||
set_tests_properties(CTestTestMemcheckDummyThreadSanitizer PROPERTIES
|
|
||||||
PASS_REGULAR_EXPRESSION
|
|
||||||
".*Memory checking results:.*data race.* - 1.*data race on vptr .ctor/dtor vs virtual call. - 1.*heap-use-after-free - 1.*thread leak - 1.*destroy of a locked mutex - 1.*double lock of a mutex - 1.*unlock of an unlocked mutex .or by a wrong thread. - 1.*read lock of a write locked mutex - 1.*read unlock of a write locked mutex - 1.*signal-unsafe call inside of a signal - 1.*signal handler spoils errno - 1.*lock-order-inversion .potential deadlock. - 1.*")
|
|
||||||
|
|
||||||
|
|
||||||
# Xcode 2.x forgets to create the output directory before linking
|
# Xcode 2.x forgets to create the output directory before linking
|
||||||
# the individual architectures.
|
# the individual architectures.
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
# this file simulates a program that has been built with thread sanitizer
|
||||||
|
# options
|
||||||
|
|
||||||
|
message("ASAN_OPTIONS = [$ENV{ASAN_OPTIONS}]")
|
||||||
|
string(REGEX REPLACE ".*log_path=\"([^\"]*)\".*" "\\1" LOG_FILE "$ENV{ASAN_OPTIONS}")
|
||||||
|
message("LOG_FILE=[${LOG_FILE}]")
|
||||||
|
|
||||||
|
# clear the log file
|
||||||
|
file(REMOVE "${LOG_FILE}.2343")
|
||||||
|
|
||||||
|
# create an error of each type of thread santizer
|
||||||
|
# these names come from tsan_report.cc in llvm
|
||||||
|
|
||||||
|
file(APPEND "${LOG_FILE}.2343"
|
||||||
|
"=================================================================
|
||||||
|
==19278== ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60080000bffc at pc 0x4009f1 bp 0x7fff82de6520 sp 0x7fff82de6518
|
||||||
|
WRITE of size 4 at 0x60080000bffc thread T0
|
||||||
|
#0 0x4009f0 (/home/kitware/msan/a.out+0x4009f0)
|
||||||
|
#1 0x7f18b02c876c (/lib/x86_64-linux-gnu/libc-2.15.so+0x2176c)
|
||||||
|
#2 0x400858 (/home/kitware/msan/a.out+0x400858)
|
||||||
|
0x60080000bffc is located 4 bytes to the right of 40-byte region [0x60080000bfd0,0x60080000bff8)
|
||||||
|
allocated by thread T0 here:
|
||||||
|
#0 0x7f18b088f9ca (/usr/lib/x86_64-linux-gnu/libasan.so.0.0.0+0x119ca)
|
||||||
|
#1 0x4009a2 (/home/kitware/msan/a.out+0x4009a2)
|
||||||
|
#2 0x7f18b02c876c (/lib/x86_64-linux-gnu/libc-2.15.so+0x2176c)
|
||||||
|
Shadow bytes around the buggy address:
|
||||||
|
0x0c017fff97a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
|
||||||
|
0x0c017fff97b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
|
||||||
|
0x0c017fff97c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
|
||||||
|
0x0c017fff97d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
|
||||||
|
0x0c017fff97e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
|
||||||
|
=>0x0c017fff97f0: fa fa fa fa fa fa fa fa fa fa 00 00 00 00 00[fa]
|
||||||
|
0x0c017fff9800:fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
|
||||||
|
0x0c017fff9810: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
|
||||||
|
0x0c017fff9820: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
|
||||||
|
0x0c017fff9830: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
|
||||||
|
0x0c017fff9840: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
|
||||||
|
Shadow byte legend (one shadow byte represents 8 application bytes):
|
||||||
|
Addressable: 00
|
||||||
|
Partially addressable: 01 02 03 04 05 06 07
|
||||||
|
Heap left redzone: fa
|
||||||
|
Heap righ redzone: fb
|
||||||
|
Freed Heap region: fd
|
||||||
|
Stack left redzone: f1
|
||||||
|
Stack mid redzone: f2
|
||||||
|
Stack right redzone: f3
|
||||||
|
Stack partial redzone: f4
|
||||||
|
Stack after return: f5
|
||||||
|
Stack use after scope: f8
|
||||||
|
Global redzone: f9
|
||||||
|
Global init order: f6
|
||||||
|
Poisoned by user: f7
|
||||||
|
ASan internal: fe
|
||||||
|
==19278== ABORTING
|
||||||
|
")
|
|
@ -0,0 +1,36 @@
|
||||||
|
# this file simulates a program that has been built with thread sanitizer
|
||||||
|
# options
|
||||||
|
|
||||||
|
message("ASAN_OPTIONS = [$ENV{ASAN_OPTIONS}]")
|
||||||
|
string(REGEX REPLACE ".*log_path=\"([^\"]*)\".*" "\\1" LOG_FILE "$ENV{ASAN_OPTIONS}")
|
||||||
|
message("LOG_FILE=[${LOG_FILE}]")
|
||||||
|
|
||||||
|
# clear the log file
|
||||||
|
file(REMOVE "${LOG_FILE}.2343")
|
||||||
|
|
||||||
|
# create an error of each type of thread santizer
|
||||||
|
# these names come from tsan_report.cc in llvm
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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).
|
||||||
|
")
|
Loading…
Reference in New Issue