diff --git a/src/main.cc b/src/main.cc index d4bbf960b7..8a698f29e1 100644 --- a/src/main.cc +++ b/src/main.cc @@ -308,6 +308,8 @@ void done_with_network() abort(); } #endif + + ZEEK_LSAN_DISABLE(); } void terminate_bro() @@ -406,6 +408,7 @@ static void bro_new_handler() int main(int argc, char** argv) { + ZEEK_LSAN_DISABLE(); std::set_new_handler(bro_new_handler); // When running unit tests, the first argument on the command line must be @@ -1052,6 +1055,13 @@ int main(int argc, char** argv) reporter->Warning("event handler never invoked: %s", handler.c_str()); } + // Enable LeakSanitizer before zeek_init() and even before executing + // top-level statements. Even though it's not bad if a leak happens only + // once at initialization, we have to assume that script-layer code causing + // such a leak can be placed in any arbitrary event handler and potentially + // cause more severe problems. + ZEEK_LSAN_ENABLE(); + if ( stmts ) { stmt_flow_type flow; diff --git a/zeek-config.h.in b/zeek-config.h.in index 343ab49363..eb208312ac 100644 --- a/zeek-config.h.in +++ b/zeek-config.h.in @@ -243,3 +243,29 @@ extern const char* BRO_VERSION_FUNCTION(); #ifdef __cplusplus } #endif + +// GCC uses __SANITIZE_ADDRESS__, Clang uses __has_feature +#if defined(__SANITIZE_ADDRESS__) + #define ZEEK_ASAN +#endif + +#if defined(__has_feature) + #if __has_feature(address_sanitizer) + #define ZEEK_ASAN + #endif +#endif + +#if defined(ZEEK_ASAN) + #include + #define ZEEK_LSAN_CHECK(x) __lsan_do_leak_check(x) + #define ZEEK_LSAN_ENABLE(x) __lsan_enable(x) + #define ZEEK_LSAN_IGNORE(x) __lsan_ignore_object(x) + #define ZEEK_LSAN_DISABLE(x) __lsan_disable(x) + #define ZEEK_LSAN_DISABLE_SCOPE(x) __lsan::ScopedDisabler x +#else + #define ZEEK_LSAN_CHECK(x) + #define ZEEK_LSAN_ENABLE(x) + #define ZEEK_LSAN_IGNORE(x) + #define ZEEK_LSAN_DISABLE(x) + #define ZEEK_LSAN_DISABLE_SCOPE(x) +#endif