diff --git a/compiler-rt/lib/lsan/lsan_common.cpp b/compiler-rt/lib/lsan/lsan_common.cpp --- a/compiler-rt/lib/lsan/lsan_common.cpp +++ b/compiler-rt/lib/lsan/lsan_common.cpp @@ -135,10 +135,11 @@ Suppression *s = nullptr; // Suppress by module name. - if (const char *module_name = - Symbolizer::GetOrInit()->GetModuleNameForPc(addr)) - if (context.Match(module_name, kSuppressionLeak, &s)) - return s; + const char *module_name = Symbolizer::GetOrInit()->GetModuleNameForPc(addr); + if (!module_name) + module_name = ""; + if (context.Match(module_name, kSuppressionLeak, &s)) + return s; // Suppress by file or function name. SymbolizedStack *frames = Symbolizer::GetOrInit()->SymbolizePC(addr); diff --git a/compiler-rt/test/lsan/TestCases/Linux/dso-unknown.cpp b/compiler-rt/test/lsan/TestCases/Linux/dso-unknown.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/lsan/TestCases/Linux/dso-unknown.cpp @@ -0,0 +1,50 @@ +// Build a library with origin tracking and an executable w/o origin tracking. +// Test that origin tracking is enabled at runtime. +// RUN: %clangxx_lsan -O0 %s -DBUILD_SO -fPIC -shared -o %t-so.so +// RUN: %clangxx_lsan -O0 %s -ldl -o %t && not %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_lsan -O0 %s -ldl -o %t -DSUPPRESS_LEAK && %run %t 2>&1 + +#ifdef BUILD_SO + +# include + +extern "C" { +void *my_alloc(unsigned sz) { return malloc(sz); } +} // extern "C" + +#else // BUILD_SO + +# include +# include +# include +# include + +# ifdef SUPPRESS_LEAK +extern "C" const char *__lsan_default_suppressions() { + return "leak:^$"; +} +# endif + +void *p; +int main(int argc, char **argv) { + + std::string path = std::string(argv[0]) + "-so.so"; + + dlerror(); + + void *handle = dlopen(path.c_str(), RTLD_LAZY); + assert(handle != 0); + typedef void *(*fn)(unsigned sz); + fn my_alloc = (fn)dlsym(handle, "my_alloc"); + + p = my_alloc(1); + p = my_alloc(2); + p = my_alloc(3); + + dlclose(handle); + return 0; +} + +#endif // BUILD_SO + +// CHECK: Direct leak