llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.23k stars 12.07k forks source link

[LSAN] LeakSanitizer false positive on macOS Aarch64 #115992

Open madsmtm opened 1 week ago

madsmtm commented 1 week ago

Building and running any program with LeakSanitizer or with AddressSanitizer's detect_leaks=1 shows a leak in the system library libobjc.A.dylib on Aarch64.

I tested this in a virtual machine as well, this problem is present in at least macOS 13.5, macOS 14.7 and macOS 15.1.

It may be an actual issue in the OS (though I doubt it), but ideally LeakSanitizer should filter it out anyhow, since it's not actionable for the user.

Full backtrace on macOS 15.1 (build 24B2083)

```console $ echo "int main() { return 0; }" > foo.c $ /opt/homebrew/opt/llvm/bin/clang -fsanitize=leak foo.c $ ./a.out a.out(5340,0x1f228bac0) malloc: nano zone abandoned due to inability to reserve vm space. ================================================================= ==5340==ERROR: LeakSanitizer: detected memory leaks Direct leak of 72 byte(s) in 1 object(s) allocated from: #0 0x0001030180f8 in malloc+0x60 (libclang_rt.lsan_osx_dynamic.dylib:arm64+0x340f8) #1 0x00018cf6fa8c in _malloc_type_malloc_outlined+0x60 (libsystem_malloc.dylib:arm64+0x1ca8c) #2 0x00018cd7aaf4 in _fetchInitializingClassList(bool)+0x34 (libobjc.A.dylib:arm64+0xaaf4) #3 0x00018cd7a9b8 in _setThisThreadIsInitializingClass(objc_class*)+0x1c (libobjc.A.dylib:arm64+0xa9b8) #4 0x00018cd7a7d4 in initializeNonMetaClass+0x234 (libobjc.A.dylib:arm64+0xa7d4) #5 0x00018cd7a638 in initializeNonMetaClass+0x98 (libobjc.A.dylib:arm64+0xa638) #6 0x00018cd7a638 in initializeNonMetaClass+0x98 (libobjc.A.dylib:arm64+0xa638) #7 0x00018cd7a638 in initializeNonMetaClass+0x98 (libobjc.A.dylib:arm64+0xa638) #8 0x00018cd98a38 in initializeAndMaybeRelock(objc_class*, objc_object*, locker_mixin>&, bool)+0xa0 (libobjc.A.dylib:arm64+0x28a38) #9 0x00018cd79f94 in lookUpImpOrForward+0x12c (libobjc.A.dylib:arm64+0x9f94) #10 0x00018cd79b80 in _objc_msgSend_uncached+0x40 (libobjc.A.dylib:arm64+0x9b80) #11 0x00018ce4bd54 in _xpc_collect_images+0xc0 (libxpc.dylib:arm64+0x2d54) #12 0x00018ce4b1b0 in _libxpc_initializer+0x424 (libxpc.dylib:arm64+0x21b0) #13 0x00019ac0d634 in libSystem_initializer+0xfc (libSystem.B.dylib:arm64+0x1634) #14 0x00018cddfd50 in invocation function for block in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const+0x110 (dyld:arm64+0xfffffffffff57d50) #15 0x00018ce1e4cc in invocation function for block in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const+0x150 (dyld:arm64+0xfffffffffff964cc) #16 0x00018ce11c34 in invocation function for block in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const+0x1ec (dyld:arm64+0xfffffffffff89c34) #17 0x00018cdc42d8 () #18 0x00018ce10bc8 in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const+0xbc (dyld:arm64+0xfffffffffff88bc8) #19 0x00018ce1dfe0 in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const+0x200 (dyld:arm64+0xfffffffffff95fe0) #20 0x00018cddfbb0 in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const+0xac (dyld:arm64+0xfffffffffff57bb0) #21 0x00018cdeabe4 in dyld4::PrebuiltLoader::runInitializers(dyld4::RuntimeState&) const+0x28 (dyld:arm64+0xfffffffffff62be4) #22 0x00018cdff8b4 in dyld4::APIs::runAllInitializersForMain()+0x50 (dyld:arm64+0xfffffffffff778b4) #23 0x00018cdc98c4 () #24 0x00018cdc8bbc () #25 0x00018cdc8058 () Indirect leak of 32 byte(s) in 1 object(s) allocated from: #0 0x000103018354 in calloc+0x64 (libclang_rt.lsan_osx_dynamic.dylib:arm64+0x34354) #1 0x00018cf6fb04 in _malloc_type_calloc_outlined+0x64 (libsystem_malloc.dylib:arm64+0x1cb04) #2 0x00018cd7ab70 in _fetchInitializingClassList(bool)+0xb0 (libobjc.A.dylib:arm64+0xab70) #3 0x00018cd7a9b8 in _setThisThreadIsInitializingClass(objc_class*)+0x1c (libobjc.A.dylib:arm64+0xa9b8) #4 0x00018cd7a7d4 in initializeNonMetaClass+0x234 (libobjc.A.dylib:arm64+0xa7d4) #5 0x00018cd7a638 in initializeNonMetaClass+0x98 (libobjc.A.dylib:arm64+0xa638) #6 0x00018cd7a638 in initializeNonMetaClass+0x98 (libobjc.A.dylib:arm64+0xa638) #7 0x00018cd7a638 in initializeNonMetaClass+0x98 (libobjc.A.dylib:arm64+0xa638) #8 0x00018cd98a38 in initializeAndMaybeRelock(objc_class*, objc_object*, locker_mixin>&, bool)+0xa0 (libobjc.A.dylib:arm64+0x28a38) #9 0x00018cd79f94 in lookUpImpOrForward+0x12c (libobjc.A.dylib:arm64+0x9f94) #10 0x00018cd79b80 in _objc_msgSend_uncached+0x40 (libobjc.A.dylib:arm64+0x9b80) #11 0x00018ce4bd54 in _xpc_collect_images+0xc0 (libxpc.dylib:arm64+0x2d54) #12 0x00018ce4b1b0 in _libxpc_initializer+0x424 (libxpc.dylib:arm64+0x21b0) #13 0x00019ac0d634 in libSystem_initializer+0xfc (libSystem.B.dylib:arm64+0x1634) #14 0x00018cddfd50 in invocation function for block in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const+0x110 (dyld:arm64+0xfffffffffff57d50) #15 0x00018ce1e4cc in invocation function for block in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const+0x150 (dyld:arm64+0xfffffffffff964cc) #16 0x00018ce11c34 in invocation function for block in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const+0x1ec (dyld:arm64+0xfffffffffff89c34) #17 0x00018cdc42d8 () #18 0x00018ce10bc8 in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const+0xbc (dyld:arm64+0xfffffffffff88bc8) #19 0x00018ce1dfe0 in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const+0x200 (dyld:arm64+0xfffffffffff95fe0) #20 0x00018cddfbb0 in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const+0xac (dyld:arm64+0xfffffffffff57bb0) #21 0x00018cdeabe4 in dyld4::PrebuiltLoader::runInitializers(dyld4::RuntimeState&) const+0x28 (dyld:arm64+0xfffffffffff62be4) #22 0x00018cdff8b4 in dyld4::APIs::runAllInitializersForMain()+0x50 (dyld:arm64+0xfffffffffff778b4) #23 0x00018cdc98c4 () #24 0x00018cdc8bbc () #25 0x00018cdc8058 () Indirect leak of 16 byte(s) in 1 object(s) allocated from: #0 0x000103018354 in calloc+0x64 (libclang_rt.lsan_osx_dynamic.dylib:arm64+0x34354) #1 0x00018cf6fb04 in _malloc_type_calloc_outlined+0x64 (libsystem_malloc.dylib:arm64+0x1cb04) #2 0x00018cd7ab3c in _fetchInitializingClassList(bool)+0x7c (libobjc.A.dylib:arm64+0xab3c) #3 0x00018cd7a9b8 in _setThisThreadIsInitializingClass(objc_class*)+0x1c (libobjc.A.dylib:arm64+0xa9b8) #4 0x00018cd7a7d4 in initializeNonMetaClass+0x234 (libobjc.A.dylib:arm64+0xa7d4) #5 0x00018cd7a638 in initializeNonMetaClass+0x98 (libobjc.A.dylib:arm64+0xa638) #6 0x00018cd7a638 in initializeNonMetaClass+0x98 (libobjc.A.dylib:arm64+0xa638) #7 0x00018cd7a638 in initializeNonMetaClass+0x98 (libobjc.A.dylib:arm64+0xa638) #8 0x00018cd98a38 in initializeAndMaybeRelock(objc_class*, objc_object*, locker_mixin>&, bool)+0xa0 (libobjc.A.dylib:arm64+0x28a38) #9 0x00018cd79f94 in lookUpImpOrForward+0x12c (libobjc.A.dylib:arm64+0x9f94) #10 0x00018cd79b80 in _objc_msgSend_uncached+0x40 (libobjc.A.dylib:arm64+0x9b80) #11 0x00018ce4bd54 in _xpc_collect_images+0xc0 (libxpc.dylib:arm64+0x2d54) #12 0x00018ce4b1b0 in _libxpc_initializer+0x424 (libxpc.dylib:arm64+0x21b0) #13 0x00019ac0d634 in libSystem_initializer+0xfc (libSystem.B.dylib:arm64+0x1634) #14 0x00018cddfd50 in invocation function for block in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const+0x110 (dyld:arm64+0xfffffffffff57d50) #15 0x00018ce1e4cc in invocation function for block in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const+0x150 (dyld:arm64+0xfffffffffff964cc) #16 0x00018ce11c34 in invocation function for block in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const+0x1ec (dyld:arm64+0xfffffffffff89c34) #17 0x00018cdc42d8 () #18 0x00018ce10bc8 in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const+0xbc (dyld:arm64+0xfffffffffff88bc8) #19 0x00018ce1dfe0 in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const+0x200 (dyld:arm64+0xfffffffffff95fe0) #20 0x00018cddfbb0 in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const+0xac (dyld:arm64+0xfffffffffff57bb0) #21 0x00018cdeabe4 in dyld4::PrebuiltLoader::runInitializers(dyld4::RuntimeState&) const+0x28 (dyld:arm64+0xfffffffffff62be4) #22 0x00018cdff8b4 in dyld4::APIs::runAllInitializersForMain()+0x50 (dyld:arm64+0xfffffffffff778b4) #23 0x00018cdc98c4 () #24 0x00018cdc8bbc () #25 0x00018cdc8058 () SUMMARY: LeakSanitizer: 120 byte(s) leaked in 3 allocation(s). ``` Same for `clang -fsanitize=address foo.c && ASAN_OPTIONS=detect_leaks=1 ./a.out`.

Clang version:

Homebrew clang version 19.1.3
Target: arm64-apple-darwin24.1.0
Thread model: posix
InstalledDir: /opt/homebrew/Cellar/llvm/19.1.3/bin
Configuration file: /opt/homebrew/etc/clang/arm64-apple-darwin24.cfg

I'm using the Clang from Homebrew here, because Apple's bundled Clang does not have LeakSanitizer enabled. The problem also reproduces with the Clang from Nixpkgs, and with rustc.

Do tell me if there's something else I can do to help resolve this!

Originally reported in https://github.com/rust-lang/rust/issues/121624. See also:

madsmtm commented 6 days ago

Not sure if this is the right way to do it, but CC @vitalybuka in case you know something?

It would be nice to get this fixed so that we can release LeakSanitizer on aarch64-apple-darwin as well in https://github.com/rust-lang/rust/pull/123617.