Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix potential use after free in MacOS / iOS impl #54

Merged
merged 3 commits into from Aug 16, 2022

Conversation

Kijewski
Copy link
Collaborator

Per Ryan Lopopolo's review:

This bit makes me a bit scared with the Dropping type and the CStr being dropped while a borrowed &str is taken from name. Is the .map(|name| name.to_owned()) a use after free?

To be sure, I'd probably restructure all of these combinators to use short circuit return to make sure the Dropping and CStr wrappers are dropped in the right order.

#50 (comment)

@Kijewski
Copy link
Collaborator Author

@lopopolo, does this implementation look sane? Could you run it in the leak sanitizer, please?

@lopopolo
Copy link
Collaborator

Implementation looks a lot easier to reason about. thank you.

I still get the leaks in LeakSan though:

$ RUSTFLAGS="-Z sanitizer=leak" cargo +nightly test --lib
   Compiling core-foundation-sys v0.8.3
error: failed to run custom build command for `core-foundation-sys v0.8.3`

Caused by:
  process didn't exit successfully: `/Users/lopopolo/dev/repos/iana-time-zone/target/debug/build/core-foundation-sys-12e9821091001b77/build-script-build` (exit status: 23)
  --- stdout
  cargo:rustc-link-lib=framework=CoreFoundation

  --- stderr

  =================================================================
  ==77653==ERROR: LeakSanitizer: detected memory leaks

  Direct leak of 1888 byte(s) in 59 object(s) allocated from:
      #0 0x10f1067fd in wrap_calloc+0x5d (librustc-nightly_rt.lsan.dylib:x86_64+0xb7fd) (BuildId: 8c28f22865823830a53915a56e9223bb240000001000000000070a0000010c00)
      #1 0x7ff801b3b84f in realizeClassWithoutSwift(objc_class*, objc_class*)+0x88 (libobjc.A.dylib:x86_64h+0x484f) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #2 0x7ff801b39b59 in map_images_nolock+0x161b (libobjc.A.dylib:x86_64h+0x2b59) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #3 0x7ff801b384db in map_images+0x42 (libobjc.A.dylib:x86_64h+0x14db) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #4 0x119bca1fa in invocation function for block in dyld4::RuntimeState::setObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*))+0x112 (dyld:x86_64+0xf1fa) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #5 0x119bc56c8 in dyld4::RuntimeState::withLoadersReadLock(void () block_pointer)+0x28 (dyld:x86_64+0xa6c8) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #6 0x119bca0e1 in dyld4::RuntimeState::setObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*))+0x51 (dyld:x86_64+0xf0e1) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #7 0x119bddd44 in dyld4::APIs::_dyld_objc_notify_register(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*))+0x4e (dyld:x86_64+0x22d44) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #8 0x7ff801b38343 in _objc_init+0x4fe (libobjc.A.dylib:x86_64h+0x1343) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #9 0x7ff801af2992 in _os_object_init+0xc (libdispatch.dylib:x86_64+0x2992) (BuildId: 5115c8efbc5732db91c671b61a79966e32000000200000000100000000050c00)
      #10 0x7ff801b001b7 in libdispatch_init+0x136 (libdispatch.dylib:x86_64+0x101b7) (BuildId: 5115c8efbc5732db91c671b61a79966e32000000200000000100000000050c00)
      #11 0x7ff80caa4894 in libSystem_initializer+0xed (libSystem.B.dylib:x86_64+0x1894) (BuildId: ba73a734cc563c50a9c8513b34b3726932000000200000000100000000050c00)
      #12 0x119bcfe4e in invocation function for block in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const+0xb5 (dyld:x86_64+0x14e4e) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #13 0x119bf6aac in invocation function for block in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const+0xf1 (dyld:x86_64+0x3baac) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #14 0x119bede25 in invocation function for block in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const+0x22c (dyld:x86_64+0x32e25) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #15 0x119bbcdb2 in dyld3::MachOFile::forEachLoadCommand(Diagnostics&, void (load_command const*, bool&) block_pointer) const+0x80 (dyld:x86_64+0x1db2) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #16 0x119bedbb6 in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const+0xb2 (dyld:x86_64+0x32bb6) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #17 0x119bf6603 in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const+0x1d1 (dyld:x86_64+0x3b603) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #18 0x119bcfd81 in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const+0x8f (dyld:x86_64+0x14d81) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #19 0x119bd6659 in dyld4::PrebuiltLoader::runInitializers(dyld4::RuntimeState&) const+0x1d (dyld:x86_64+0x1b659) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #20 0x119be376d in dyld4::APIs::runAllInitializersForMain()+0x25 (dyld:x86_64+0x2876d) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #21 0x119bc138c in dyld4::prepare(dyld4::APIs&, dyld3::MachOAnalyzer const*)+0xd72 (dyld:x86_64+0x638c) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #22 0x119bc04e3 in start+0x183 (dyld:x86_64+0x54e3) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)

  Direct leak of 1888 byte(s) in 59 object(s) allocated from:
      #0 0x10f1067fd in wrap_calloc+0x5d (librustc-nightly_rt.lsan.dylib:x86_64+0xb7fd) (BuildId: 8c28f22865823830a53915a56e9223bb240000001000000000070a0000010c00)
      #1 0x7ff801b3b84f in realizeClassWithoutSwift(objc_class*, objc_class*)+0x88 (libobjc.A.dylib:x86_64h+0x484f) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #2 0x7ff801b3b91b in realizeClassWithoutSwift(objc_class*, objc_class*)+0x154 (libobjc.A.dylib:x86_64h+0x491b) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #3 0x7ff801b39b59 in map_images_nolock+0x161b (libobjc.A.dylib:x86_64h+0x2b59) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #4 0x7ff801b384db in map_images+0x42 (libobjc.A.dylib:x86_64h+0x14db) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #5 0x119bca1fa in invocation function for block in dyld4::RuntimeState::setObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*))+0x112 (dyld:x86_64+0xf1fa) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #6 0x119bc56c8 in dyld4::RuntimeState::withLoadersReadLock(void () block_pointer)+0x28 (dyld:x86_64+0xa6c8) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #7 0x119bca0e1 in dyld4::RuntimeState::setObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*))+0x51 (dyld:x86_64+0xf0e1) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #8 0x119bddd44 in dyld4::APIs::_dyld_objc_notify_register(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*))+0x4e (dyld:x86_64+0x22d44) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #9 0x7ff801b38343 in _objc_init+0x4fe (libobjc.A.dylib:x86_64h+0x1343) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #10 0x7ff801af2992 in _os_object_init+0xc (libdispatch.dylib:x86_64+0x2992) (BuildId: 5115c8efbc5732db91c671b61a79966e32000000200000000100000000050c00)
      #11 0x7ff801b001b7 in libdispatch_init+0x136 (libdispatch.dylib:x86_64+0x101b7) (BuildId: 5115c8efbc5732db91c671b61a79966e32000000200000000100000000050c00)
      #12 0x7ff80caa4894 in libSystem_initializer+0xed (libSystem.B.dylib:x86_64+0x1894) (BuildId: ba73a734cc563c50a9c8513b34b3726932000000200000000100000000050c00)
      #13 0x119bcfe4e in invocation function for block in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const+0xb5 (dyld:x86_64+0x14e4e) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #14 0x119bf6aac in invocation function for block in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const+0xf1 (dyld:x86_64+0x3baac) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #15 0x119bede25 in invocation function for block in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const+0x22c (dyld:x86_64+0x32e25) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #16 0x119bbcdb2 in dyld3::MachOFile::forEachLoadCommand(Diagnostics&, void (load_command const*, bool&) block_pointer) const+0x80 (dyld:x86_64+0x1db2) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #17 0x119bedbb6 in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const+0xb2 (dyld:x86_64+0x32bb6) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #18 0x119bf6603 in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const+0x1d1 (dyld:x86_64+0x3b603) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #19 0x119bcfd81 in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const+0x8f (dyld:x86_64+0x14d81) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #20 0x119bd6659 in dyld4::PrebuiltLoader::runInitializers(dyld4::RuntimeState&) const+0x1d (dyld:x86_64+0x1b659) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #21 0x119be376d in dyld4::APIs::runAllInitializersForMain()+0x25 (dyld:x86_64+0x2876d) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #22 0x119bc138c in dyld4::prepare(dyld4::APIs&, dyld3::MachOAnalyzer const*)+0xd72 (dyld:x86_64+0x638c) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #23 0x119bc04e3 in start+0x183 (dyld:x86_64+0x54e3) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)

  Direct leak of 160 byte(s) in 5 object(s) allocated from:
      #0 0x10f1067fd in wrap_calloc+0x5d (librustc-nightly_rt.lsan.dylib:x86_64+0xb7fd) (BuildId: 8c28f22865823830a53915a56e9223bb240000001000000000070a0000010c00)
      #1 0x7ff801b3b84f in realizeClassWithoutSwift(objc_class*, objc_class*)+0x88 (libobjc.A.dylib:x86_64h+0x484f) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #2 0x7ff801b3b91b in realizeClassWithoutSwift(objc_class*, objc_class*)+0x154 (libobjc.A.dylib:x86_64h+0x491b) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #3 0x7ff801b3b8f8 in realizeClassWithoutSwift(objc_class*, objc_class*)+0x131 (libobjc.A.dylib:x86_64h+0x48f8) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #4 0x7ff801b39b59 in map_images_nolock+0x161b (libobjc.A.dylib:x86_64h+0x2b59) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #5 0x7ff801b384db in map_images+0x42 (libobjc.A.dylib:x86_64h+0x14db) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #6 0x119bca1fa in invocation function for block in dyld4::RuntimeState::setObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*))+0x112 (dyld:x86_64+0xf1fa) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #7 0x119bc56c8 in dyld4::RuntimeState::withLoadersReadLock(void () block_pointer)+0x28 (dyld:x86_64+0xa6c8) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #8 0x119bca0e1 in dyld4::RuntimeState::setObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*))+0x51 (dyld:x86_64+0xf0e1) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #9 0x119bddd44 in dyld4::APIs::_dyld_objc_notify_register(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*))+0x4e (dyld:x86_64+0x22d44) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #10 0x7ff801b38343 in _objc_init+0x4fe (libobjc.A.dylib:x86_64h+0x1343) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #11 0x7ff801af2992 in _os_object_init+0xc (libdispatch.dylib:x86_64+0x2992) (BuildId: 5115c8efbc5732db91c671b61a79966e32000000200000000100000000050c00)
      #12 0x7ff801b001b7 in libdispatch_init+0x136 (libdispatch.dylib:x86_64+0x101b7) (BuildId: 5115c8efbc5732db91c671b61a79966e32000000200000000100000000050c00)
      #13 0x7ff80caa4894 in libSystem_initializer+0xed (libSystem.B.dylib:x86_64+0x1894) (BuildId: ba73a734cc563c50a9c8513b34b3726932000000200000000100000000050c00)
      #14 0x119bcfe4e in invocation function for block in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const+0xb5 (dyld:x86_64+0x14e4e) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #15 0x119bf6aac in invocation function for block in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const+0xf1 (dyld:x86_64+0x3baac) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #16 0x119bede25 in invocation function for block in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const+0x22c (dyld:x86_64+0x32e25) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #17 0x119bbcdb2 in dyld3::MachOFile::forEachLoadCommand(Diagnostics&, void (load_command const*, bool&) block_pointer) const+0x80 (dyld:x86_64+0x1db2) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #18 0x119bedbb6 in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const+0xb2 (dyld:x86_64+0x32bb6) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #19 0x119bf6603 in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const+0x1d1 (dyld:x86_64+0x3b603) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #20 0x119bcfd81 in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const+0x8f (dyld:x86_64+0x14d81) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #21 0x119bd6659 in dyld4::PrebuiltLoader::runInitializers(dyld4::RuntimeState&) const+0x1d (dyld:x86_64+0x1b659) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #22 0x119be376d in dyld4::APIs::runAllInitializersForMain()+0x25 (dyld:x86_64+0x2876d) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #23 0x119bc138c in dyld4::prepare(dyld4::APIs&, dyld3::MachOAnalyzer const*)+0xd72 (dyld:x86_64+0x638c) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #24 0x119bc04e3 in start+0x183 (dyld:x86_64+0x54e3) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)

  Direct leak of 160 byte(s) in 5 object(s) allocated from:
      #0 0x10f1067fd in wrap_calloc+0x5d (librustc-nightly_rt.lsan.dylib:x86_64+0xb7fd) (BuildId: 8c28f22865823830a53915a56e9223bb240000001000000000070a0000010c00)
      #1 0x7ff801b3b84f in realizeClassWithoutSwift(objc_class*, objc_class*)+0x88 (libobjc.A.dylib:x86_64h+0x484f) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #2 0x7ff801b3b8f8 in realizeClassWithoutSwift(objc_class*, objc_class*)+0x131 (libobjc.A.dylib:x86_64h+0x48f8) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #3 0x7ff801b39b59 in map_images_nolock+0x161b (libobjc.A.dylib:x86_64h+0x2b59) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #4 0x7ff801b384db in map_images+0x42 (libobjc.A.dylib:x86_64h+0x14db) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #5 0x119bca1fa in invocation function for block in dyld4::RuntimeState::setObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*))+0x112 (dyld:x86_64+0xf1fa) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #6 0x119bc56c8 in dyld4::RuntimeState::withLoadersReadLock(void () block_pointer)+0x28 (dyld:x86_64+0xa6c8) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #7 0x119bca0e1 in dyld4::RuntimeState::setObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*))+0x51 (dyld:x86_64+0xf0e1) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #8 0x119bddd44 in dyld4::APIs::_dyld_objc_notify_register(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*))+0x4e (dyld:x86_64+0x22d44) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #9 0x7ff801b38343 in _objc_init+0x4fe (libobjc.A.dylib:x86_64h+0x1343) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #10 0x7ff801af2992 in _os_object_init+0xc (libdispatch.dylib:x86_64+0x2992) (BuildId: 5115c8efbc5732db91c671b61a79966e32000000200000000100000000050c00)
      #11 0x7ff801b001b7 in libdispatch_init+0x136 (libdispatch.dylib:x86_64+0x101b7) (BuildId: 5115c8efbc5732db91c671b61a79966e32000000200000000100000000050c00)
      #12 0x7ff80caa4894 in libSystem_initializer+0xed (libSystem.B.dylib:x86_64+0x1894) (BuildId: ba73a734cc563c50a9c8513b34b3726932000000200000000100000000050c00)
      #13 0x119bcfe4e in invocation function for block in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const+0xb5 (dyld:x86_64+0x14e4e) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #14 0x119bf6aac in invocation function for block in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const+0xf1 (dyld:x86_64+0x3baac) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #15 0x119bede25 in invocation function for block in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const+0x22c (dyld:x86_64+0x32e25) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #16 0x119bbcdb2 in dyld3::MachOFile::forEachLoadCommand(Diagnostics&, void (load_command const*, bool&) block_pointer) const+0x80 (dyld:x86_64+0x1db2) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #17 0x119bedbb6 in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const+0xb2 (dyld:x86_64+0x32bb6) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #18 0x119bf6603 in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const+0x1d1 (dyld:x86_64+0x3b603) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #19 0x119bcfd81 in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const+0x8f (dyld:x86_64+0x14d81) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #20 0x119bd6659 in dyld4::PrebuiltLoader::runInitializers(dyld4::RuntimeState&) const+0x1d (dyld:x86_64+0x1b659) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #21 0x119be376d in dyld4::APIs::runAllInitializersForMain()+0x25 (dyld:x86_64+0x2876d) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #22 0x119bc138c in dyld4::prepare(dyld4::APIs&, dyld3::MachOAnalyzer const*)+0xd72 (dyld:x86_64+0x638c) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #23 0x119bc04e3 in start+0x183 (dyld:x86_64+0x54e3) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)

  Direct leak of 32 byte(s) in 1 object(s) allocated from:
      #0 0x10f1067fd in wrap_calloc+0x5d (librustc-nightly_rt.lsan.dylib:x86_64+0xb7fd) (BuildId: 8c28f22865823830a53915a56e9223bb240000001000000000070a0000010c00)
      #1 0x7ff801b3b84f in realizeClassWithoutSwift(objc_class*, objc_class*)+0x88 (libobjc.A.dylib:x86_64h+0x484f) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #2 0x7ff801b3b91b in realizeClassWithoutSwift(objc_class*, objc_class*)+0x154 (libobjc.A.dylib:x86_64h+0x491b) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #3 0x7ff801b3b8f8 in realizeClassWithoutSwift(objc_class*, objc_class*)+0x131 (libobjc.A.dylib:x86_64h+0x48f8) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #4 0x7ff801b3b8f8 in realizeClassWithoutSwift(objc_class*, objc_class*)+0x131 (libobjc.A.dylib:x86_64h+0x48f8) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #5 0x7ff801b39b59 in map_images_nolock+0x161b (libobjc.A.dylib:x86_64h+0x2b59) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #6 0x7ff801b384db in map_images+0x42 (libobjc.A.dylib:x86_64h+0x14db) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #7 0x119bca1fa in invocation function for block in dyld4::RuntimeState::setObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*))+0x112 (dyld:x86_64+0xf1fa) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #8 0x119bc56c8 in dyld4::RuntimeState::withLoadersReadLock(void () block_pointer)+0x28 (dyld:x86_64+0xa6c8) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #9 0x119bca0e1 in dyld4::RuntimeState::setObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*))+0x51 (dyld:x86_64+0xf0e1) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #10 0x119bddd44 in dyld4::APIs::_dyld_objc_notify_register(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*))+0x4e (dyld:x86_64+0x22d44) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #11 0x7ff801b38343 in _objc_init+0x4fe (libobjc.A.dylib:x86_64h+0x1343) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #12 0x7ff801af2992 in _os_object_init+0xc (libdispatch.dylib:x86_64+0x2992) (BuildId: 5115c8efbc5732db91c671b61a79966e32000000200000000100000000050c00)
      #13 0x7ff801b001b7 in libdispatch_init+0x136 (libdispatch.dylib:x86_64+0x101b7) (BuildId: 5115c8efbc5732db91c671b61a79966e32000000200000000100000000050c00)
      #14 0x7ff80caa4894 in libSystem_initializer+0xed (libSystem.B.dylib:x86_64+0x1894) (BuildId: ba73a734cc563c50a9c8513b34b3726932000000200000000100000000050c00)
      #15 0x119bcfe4e in invocation function for block in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const+0xb5 (dyld:x86_64+0x14e4e) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #16 0x119bf6aac in invocation function for block in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const+0xf1 (dyld:x86_64+0x3baac) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #17 0x119bede25 in invocation function for block in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const+0x22c (dyld:x86_64+0x32e25) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #18 0x119bbcdb2 in dyld3::MachOFile::forEachLoadCommand(Diagnostics&, void (load_command const*, bool&) block_pointer) const+0x80 (dyld:x86_64+0x1db2) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #19 0x119bedbb6 in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const+0xb2 (dyld:x86_64+0x32bb6) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #20 0x119bf6603 in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const+0x1d1 (dyld:x86_64+0x3b603) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #21 0x119bcfd81 in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const+0x8f (dyld:x86_64+0x14d81) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #22 0x119bd6659 in dyld4::PrebuiltLoader::runInitializers(dyld4::RuntimeState&) const+0x1d (dyld:x86_64+0x1b659) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #23 0x119be376d in dyld4::APIs::runAllInitializersForMain()+0x25 (dyld:x86_64+0x2876d) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #24 0x119bc138c in dyld4::prepare(dyld4::APIs&, dyld3::MachOAnalyzer const*)+0xd72 (dyld:x86_64+0x638c) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #25 0x119bc04e3 in start+0x183 (dyld:x86_64+0x54e3) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)

  Direct leak of 32 byte(s) in 1 object(s) allocated from:
      #0 0x10f1067fd in wrap_calloc+0x5d (librustc-nightly_rt.lsan.dylib:x86_64+0xb7fd) (BuildId: 8c28f22865823830a53915a56e9223bb240000001000000000070a0000010c00)
      #1 0x7ff801b3b84f in realizeClassWithoutSwift(objc_class*, objc_class*)+0x88 (libobjc.A.dylib:x86_64h+0x484f) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #2 0x7ff801b3b8f8 in realizeClassWithoutSwift(objc_class*, objc_class*)+0x131 (libobjc.A.dylib:x86_64h+0x48f8) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #3 0x7ff801b3b8f8 in realizeClassWithoutSwift(objc_class*, objc_class*)+0x131 (libobjc.A.dylib:x86_64h+0x48f8) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #4 0x7ff801b39b59 in map_images_nolock+0x161b (libobjc.A.dylib:x86_64h+0x2b59) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #5 0x7ff801b384db in map_images+0x42 (libobjc.A.dylib:x86_64h+0x14db) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #6 0x119bca1fa in invocation function for block in dyld4::RuntimeState::setObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*))+0x112 (dyld:x86_64+0xf1fa) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #7 0x119bc56c8 in dyld4::RuntimeState::withLoadersReadLock(void () block_pointer)+0x28 (dyld:x86_64+0xa6c8) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #8 0x119bca0e1 in dyld4::RuntimeState::setObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*))+0x51 (dyld:x86_64+0xf0e1) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #9 0x119bddd44 in dyld4::APIs::_dyld_objc_notify_register(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*))+0x4e (dyld:x86_64+0x22d44) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #10 0x7ff801b38343 in _objc_init+0x4fe (libobjc.A.dylib:x86_64h+0x1343) (BuildId: dad8610317e93016930d02cad81a5ed932000000200000000100000000050c00)
      #11 0x7ff801af2992 in _os_object_init+0xc (libdispatch.dylib:x86_64+0x2992) (BuildId: 5115c8efbc5732db91c671b61a79966e32000000200000000100000000050c00)
      #12 0x7ff801b001b7 in libdispatch_init+0x136 (libdispatch.dylib:x86_64+0x101b7) (BuildId: 5115c8efbc5732db91c671b61a79966e32000000200000000100000000050c00)
      #13 0x7ff80caa4894 in libSystem_initializer+0xed (libSystem.B.dylib:x86_64+0x1894) (BuildId: ba73a734cc563c50a9c8513b34b3726932000000200000000100000000050c00)
      #14 0x119bcfe4e in invocation function for block in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const+0xb5 (dyld:x86_64+0x14e4e) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #15 0x119bf6aac in invocation function for block in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const+0xf1 (dyld:x86_64+0x3baac) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #16 0x119bede25 in invocation function for block in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const+0x22c (dyld:x86_64+0x32e25) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #17 0x119bbcdb2 in dyld3::MachOFile::forEachLoadCommand(Diagnostics&, void (load_command const*, bool&) block_pointer) const+0x80 (dyld:x86_64+0x1db2) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #18 0x119bedbb6 in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const+0xb2 (dyld:x86_64+0x32bb6) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #19 0x119bf6603 in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const+0x1d1 (dyld:x86_64+0x3b603) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #20 0x119bcfd81 in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const+0x8f (dyld:x86_64+0x14d81) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #21 0x119bd6659 in dyld4::PrebuiltLoader::runInitializers(dyld4::RuntimeState&) const+0x1d (dyld:x86_64+0x1b659) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #22 0x119be376d in dyld4::APIs::runAllInitializersForMain()+0x25 (dyld:x86_64+0x2876d) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #23 0x119bc138c in dyld4::prepare(dyld4::APIs&, dyld3::MachOAnalyzer const*)+0xd72 (dyld:x86_64+0x638c) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)
      #24 0x119bc04e3 in start+0x183 (dyld:x86_64+0x54e3) (BuildId: f71fb3ca5fcc35779457b047888a46d132000000200000000100000000050c00)

  SUMMARY: LeakSanitizer: 4160 byte(s) leaked in 130 allocation(s).

@lopopolo
Copy link
Collaborator

hmm I also get these leaks in 0.1.42 on my machine too. Is this a bug upstream in core-foundation-sys? Or are we somehow using it incorrectly here.

@Kijewski
Copy link
Collaborator Author

Could you test the stress-test, please? It calls get_timezone() 100,000 times, so if this is actually a leak, and not some sort of automatic caching by CFTimeZoneCopySystem(), it should be very apparent.

@lopopolo
Copy link
Collaborator

At 9454971, running RUSTFLAGS="-Z sanitizer=leak" cargo +nightly run --target x86_64-apple-darwin --example stress-test, leaksan gives:

SUMMARY: LeakSanitizer: 7908 byte(s) leaked in 244 allocation(s).

It's a big dump, I'm not sure if you want the whole thing. Here's an interesting snippet:

Indirect leak of 36 byte(s) in 1 object(s) allocated from:
    #0 0x101fdb5b8 in wrap_malloc+0x58 (librustc-nightly_rt.lsan.dylib:x86_64+0xb5b8) (BuildId: 8c28f22865823830a53915a56e9223bb240000001000000000070a0000010c00)
    #1 0x7ff8019dc40d in _Block_copy+0x5d (libsystem_blocks.dylib:x86_64+0x140d) (BuildId: 13e634c62f3f3bd5b343846e056eb79232000000200000000100000000050c00)
    #2 0x7ff8019dc4d8 in _Block_object_assign+0x57 (libsystem_blocks.dylib:x86_64+0x14d8) (BuildId: 13e634c62f3f3bd5b343846e056eb79232000000200000000100000000050c00)
    #3 0x7ff8019dc474 in _Block_copy+0xc4 (libsystem_blocks.dylib:x86_64+0x1474) (BuildId: 13e634c62f3f3bd5b343846e056eb79232000000200000000100000000050c00)
    #4 0x7ff801af20a7 in _dispatch_Block_copy+0x15 (libdispatch.dylib:x86_64+0x20a7) (BuildId: 5115c8efbc5732db91c671b61a79966e32000000200000000100000000050c00)
    #5 0x7ff801b06467 in _dispatch_source_set_handler+0x5b (libdispatch.dylib:x86_64+0x16467) (BuildId: 5115c8efbc5732db91c671b61a79966e32000000200000000100000000050c00)
    #6 0x101fdaed6 in wrap_dispatch_source_set_cancel_handler+0x56 (librustc-nightly_rt.lsan.dylib:x86_64+0xaed6) (BuildId: 8c28f22865823830a53915a56e9223bb240000001000000000070a0000010c00)
    #7 0x7ff804714d4a  (libsystem_notify.dylib:x86_64+0x8d4a) (BuildId: f46a1b4655a03ad084d77a9c79f69c8332000000200000000100000000050c00)
    #8 0x7ff804712a67  (libsystem_notify.dylib:x86_64+0x6a67) (BuildId: f46a1b4655a03ad084d77a9c79f69c8332000000200000000100000000050c00)
    #9 0x7ff804716618  (libsystem_notify.dylib:x86_64+0xa618) (BuildId: f46a1b4655a03ad084d77a9c79f69c8332000000200000000100000000050c00)
    #10 0x7ff801e2e6db in ___CFNotificationCenterInitializeDependentNotificationIfNecessary_block_invoke+0x193 (CoreFoundation:x86_64h+0x13d6db) (BuildId: c39123bf9d623577a11f0a97cc4d999132000000200000000100000000050c00)
    #11 0x7ff801af3316 in _dispatch_client_callout+0x7 (libdispatch.dylib:x86_64+0x3316) (BuildId: 5115c8efbc5732db91c671b61a79966e32000000200000000100000000050c00)
    #12 0x7ff801af44f9 in _dispatch_once_callout+0x13 (libdispatch.dylib:x86_64+0x44f9) (BuildId: 5115c8efbc5732db91c671b61a79966e32000000200000000100000000050c00)
    #13 0x7ff801e2e540 in _CFNotificationCenterInitializeDependentNotificationIfNecessary+0x175 (CoreFoundation:x86_64h+0x13d540) (BuildId: c39123bf9d623577a11f0a97cc4d999132000000200000000100000000050c00)
    #14 0x7ff801d41aea in +[NSTimeZone systemTimeZone]+0x28d (CoreFoundation:x86_64h+0x50aea) (BuildId: c39123bf9d623577a11f0a97cc4d999132000000200000000100000000050c00)
    #15 0x7ff801df04fd in CFTimeZoneCopySystem+0x22 (CoreFoundation:x86_64h+0xff4fd) (BuildId: c39123bf9d623577a11f0a97cc4d999132000000200000000100000000050c00)
    #16 0x101d2a58d in iana_time_zone::platform::get_timezone::hc90ea79a11ab3aad+0x1d (stress-test:x86_64+0x10000f58d) (BuildId: 404a47e0d03937528ef558493cd6d6ae32000000200000000100000000000c00)
    #17 0x101d2a548 in iana_time_zone::platform::get_timezone_inner::h56acec0f12a3839c+0x18 (stress-test:x86_64+0x10000f548) (BuildId: 404a47e0d03937528ef558493cd6d6ae32000000200000000100000000000c00)
    #18 0x101d1ef53 in iana_time_zone::get_timezone::hdc503d00c9d2fcd4 lib.rs:83
    #19 0x101d24192 in stress_test::main::_$u7b$$u7b$closure$u7d$$u7d$::hd4bfb10bfcee7e5f stress-test.rs:16
    #20 0x101d27e3c in std::sys_common::backtrace::__rust_begin_short_backtrace::hcd13bbf03f08097f backtrace.rs:122
    #21 0x101d1ffdc in std::thread::Builder::spawn_unchecked_::_$u7b$$u7b$closure$u7d$$u7d$::_$u7b$$u7b$closure$u7d$$u7d$::h21ba5fed9190eff8 mod.rs:505
    #22 0x101d27e8c in _$LT$core..panic..unwind_safe..AssertUnwindSafe$LT$F$GT$$u20$as$u20$core..ops..function..FnOnce$LT$$LP$$RP$$GT$$GT$::call_once::ha52dffafb7a11719 unwind_safe.rs:271
    #23 0x101d248f2 in std::panicking::try::do_call::h288e3cd56a0da97f panicking.rs:492
    #24 0x101d24a3c in __rust_try+0x1c (stress-test:x86_64+0x100009a3c) (BuildId: 404a47e0d03937528ef558493cd6d6ae32000000200000000100000000000c00)
    #25 0x101d247fa in std::panicking::try::h90031b9bcb904824 panicking.rs:456
    #26 0x101d23bd3 in std::panic::catch_unwind::h98ef9dc0b6174d69 panic.rs:137
    #27 0x101d1fe86 in std::thread::Builder::spawn_unchecked_::_$u7b$$u7b$closure$u7d$$u7d$::h9b66d2eb56332215 mod.rs:504
    #28 0x101d209d0 in core::ops::function::FnOnce::call_once$u7b$$u7b$vtable.shim$u7d$$u7d$::h1ecccb6bcfbe662a function.rs:248
    #29 0x101d4d376 in std::sys::unix::thread::Thread::new::thread_start::hb5270d7edd00b2a3+0x26 (stress-test:x86_64+0x100032376) (BuildId: 404a47e0d03937528ef558493cd6d6ae32000000200000000100000000000c00)

Full log: leaksan.log.

src/tz_macos.rs Outdated

// Get system time zone, and its name.
let tz = Dropping::new(CFTimeZoneCopySystem())?;
let name = Dropping::new(CFTimeZoneGetName(tz.0))?;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is UB since Dropping will free an un-owned pointer.

See: https://developer.apple.com/documentation/corefoundation/1543519-cftimezonegetname

A string containing the geopolitical region name that identifies tz. Ownership follows the The Get Rule.

The Get Rule

If you receive an object from any Core Foundation function other than a creation or copy function—such as a Get function—you do not own it and cannot be certain of the object’s life span. If you want to ensure that such an object is not disposed of while you are using it, you must claim ownership (with the CFRetain function). You are then responsible for relinquishing ownership when you have finished with it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, thanks, fixed in the next commit. I guess that this could cause a leak, when the reference counter wraps around because it was decremented once too often.

Kijewski added a commit to Kijewski/iana-time-zone that referenced this pull request Aug 15, 2022
Kijewski added a commit to Kijewski/iana-time-zone that referenced this pull request Aug 15, 2022
buf.as_mut_ptr(),
buf.len() as isize,
&mut buf_bytes,
) != range.length
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This return value is the number of encoding-aware characters, not the length of the byte string.

the length stored in the out parameter buf_bytes is the number of bytes copied.

https://developer.apple.com/documentation/corefoundation/1543006-cfstringgetbytes

Copy link
Collaborator Author

@Kijewski Kijewski Aug 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I check that all characters in the original encoding were consumed, not more or less. But I use buf_bytes to build the UTF-8 string. (At least that's what I want to do? Am I wrong in here?)

core-foundation even asserts that the length matches: https://docs.rs/core-foundation/0.9.3/src/core_foundation/string.rs.html#82

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh I see.

https://developer.apple.com/documentation/corefoundation/1543006-cfstringgetbytes

Return Value

The number of characters converted.

@lopopolo
Copy link
Collaborator

This is what I ended up with, which based on my reading of the core foundation docs is the simplest set of APIs that requires the least memory management in Rust:

#[inline]
unsafe fn get_timezone() -> Option<String> {
    // Get system time zone, and its name.
    let tz = Dropping::new(CFTimeZoneCopySystem())?;
    let name = CFTimeZoneGetName(tz.0);
    if name.is_null() {
        return None;
    }

    let cstr = CFStringGetCStringPtr(name, kCFStringEncodingUTF8);
    if cstr.is_null() {
        return None;
    }
    let cstr = std::ffi::CStr::from_ptr(cstr);
    let s = cstr.to_str().ok()?;
    Some(s.to_owned())
}

@lopopolo
Copy link
Collaborator

the leak sanitizer bits are I think a red herring. All of the leaks are deep in the objective-c runtime.

@astraw
Copy link
Member

astraw commented Aug 15, 2022

@Kijewski @lopopolo thanks for the investigations here. I've invited you both to be maintainers of the repo.

@lopopolo would you be willing to update the PR with your version and @Kijewski, if you agree, can you merge it in?

@astraw
Copy link
Member

astraw commented Aug 15, 2022

@Kijewski I also invited you to be an owner on crates.io. You can publish this as the next release if you like, else let me know and I will do it.

@Kijewski
Copy link
Collaborator Author

@astraw, thank you! I accepted both invitation.

@lopopolo, my implementation is the same now as yours, except it does the character set conversion if the name is not in UTF-8. Do you think we can simply omit the second part? Other implementations like abseil don't have the CFStringGetCStringPtr shortcut at all: time_zone_lookup.cc.

@lopopolo
Copy link
Collaborator

thanks @astraw I've accepted the GitHub invitation.

@Kijewski: I'll give this a review once I get our of work today. If things look good, I'll merge (I know this is backwards from what @astraw suggested but it looks like you've done the PR updating part 😅)

Copy link
Collaborator

@lopopolo lopopolo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a couple of questions @Kijewski but this looks good to me.

I can merge once we resolve all of the outstanding conversations.

}

// Otherwise convert the name to UTF-8.
let mut buf = [0; MAX_LEN];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love that we're avoiding the heap allocation here but would like to make sure our assumptions are valid. What do you think about adding an assert that MAX_LEN is sufficient? If the assert triggers, we at least get a shot at getting a bug report.

core-foundation has a similar assert for the vector they allocate and abseil grabs the length to resize a vector:

https://github.com/servo/core-foundation-rs/blob/e64eab3ecad0071aff2f08aa4254f797a85475d1/core-foundation/src/string.rs#L137-L141

https://github.com/servo/core-foundation-rs/blob/e64eab3ecad0071aff2f08aa4254f797a85475d1/core-foundation/src/string.rs#L57-L68

I think the core-foundation crate is likely to be more correct given it doesn't make any assumptions about the CFString's encoding.

https://github.com/abseil/abseil-cpp/blob/59cba2b50dd689010f338c63db95ca164f195798/absl/time/internal/cctz/src/time_zone_lookup.cc#L142-L143

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh I see now, the check below for buf_bytes being in range checks for this. All good.

let mut buf_bytes = 0;
let range = CFRange {
location: 0,
length: CFStringGetLength(name),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: this length is "character length" not byte length.

https://developer.apple.com/documentation/corefoundation/1542853-cfstringgetlength

Return Value

The number (in terms of UTF-16 code pairs) of characters stored in theString.

buf.as_mut_ptr(),
buf.len() as isize,
&mut buf_bytes,
) != range.length
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh I see.

https://developer.apple.com/documentation/corefoundation/1543006-cfstringgetbytes

Return Value

The number of characters converted.

// Could not convert the name.
None
} else if !(1..MAX_LEN as isize).contains(&buf_bytes) {
// The name should not be empty, or excessively long.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we want the excessively long case to be a panic?

return None;
}

// If the name is encoded in UTF-8, copy it directly.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for adding these comments outlining the phases of this function. 🎉

@lopopolo lopopolo mentioned this pull request Aug 15, 2022
@astraw astraw changed the title Fix potential use after in MacOS / iOS impl Fix potential use after free in MacOS / iOS impl Aug 15, 2022
@astraw
Copy link
Member

astraw commented Aug 15, 2022

While I have not dug in deeply myself, this looks good to me. Shall I merge and publish a release? @Kijewski you are also welcome to do so.

@lopopolo
Copy link
Collaborator

Sounds good to me @astraw 👍

Per Ryan Lopopolo's review:

> This bit makes me a bit scared with the `Dropping` type and the `CStr`
  being dropped while a borrowed `&str` is taken from name. Is the
  `.map(|name| name.to_owned())` a use after free?
>
> To be sure, I'd probably restructure all of these combinators to use
  short circuit return to make sure the `Dropping` and `CStr` wrappers
  are dropped in the right order.

<strawlab#50 (comment)>
Though it is unlikely that the time zone is stored in an encoding other
than UTF-8, it's not much work add to support for this edge case.
@Kijewski Kijewski merged commit 46ac343 into strawlab:main Aug 16, 2022
@Kijewski Kijewski deleted the pr-macos-use-after-free branch August 16, 2022 03:16
@Kijewski
Copy link
Collaborator Author

Thank you both very much! Released as v0.1.45.

@alex
Copy link

alex commented Aug 16, 2022

If there's a UAF here, it'd be much appreciated if you filed a rustsec advisory so folks will know to update: https://github.com/RustSec/advisory-db/blob/main/CONTRIBUTING.md

Thanks!

@Kijewski
Copy link
Collaborator Author

Kijewski commented Aug 16, 2022

@alex, I yanked the affected versions. Do you think I should still file an advisory? I guess the answer is probably "yes, of course".

@alex
Copy link

alex commented Aug 16, 2022

Yes, advisories are useful: they help folks who are already pinned in their Cargo.lock, they let folks know the details of the upgrade, and they provide a data set for folks looking to improve rust/libraries with new/useful safe abstractions.

@Kijewski
Copy link
Collaborator Author

Filed as rustsec/advisory-db#1366. Thank you for the suggestion, @alex! Better safe than sorry.

@lopopolo
Copy link
Collaborator

@esheppa
Copy link

esheppa commented Aug 17, 2022

Thanks for this @Kijewski and thanks for the review work @lopopolo.

One thought I had upon reading about CFRelease is that perhaps we should have a null check in the Drop implementation for Dropping:

impl<T> Drop for Dropping<T> {
    #[inline]
    fn drop(&mut self) {
        if !self.0.is_null() {
            unsafe { CFRelease(self.0 as CFTypeRef) };
        } 

    }
}

or potentially this is not needed as we have already asserted on creation of the Dropping that the pointer is not null?

@Kijewski
Copy link
Collaborator Author

Thank you for reviewing the code, too, @esheppa! I take it as an invariant here that no Dropping with an invalid pointer is created. IMO this is good enough.

It is entirely possible that the exactly same byte code would be generated with the code you've posted, since the compiler should know that it just checked that the pointer isn't null and the method is inlined. I guess I should investigate this for the next time. If the compiler is smart enough, then we should let it evaluate the invariants.

@esheppa
Copy link

esheppa commented Aug 17, 2022

Only thought here is that if the timezone is changed while this code is executing, potentially the pointer could be invalidated? I'm not sure whether it would actually return is_null() == true in that case however, and instead would continue to not be null and just point to potentially outdated / invalid data?

@Kijewski
Copy link
Collaborator Author

To fix the bug I investigated a bit, and found Apple actually released the source code for CFTimeZoneCopySystem() and related functions: CFTimeZone.c:786. (To people more familiar with the eco system this might have been obvious.)

The CFTimeZoneRef we get from CFTimeZoneCopySystem() is reference counted. So even if the time zone is changed in the mean time, we still have a valid pointer. The contained string remains valid (at least) until we CFRelease() the pointer.

@esheppa
Copy link

esheppa commented Aug 17, 2022

So even if the time zone is changed in the mean time, we still have a valid pointer. The contained string remains valid (at least) until we CFRelease() the pointer.

Makes sense!

Just noticed one other potential thing - could we just remove Dropping entirely and CFRelease the CFTimeZoneRef immediately after running CFTimeZoneGetName?

@Kijewski
Copy link
Collaborator Author

The pointer returned by CFTimeZoneGetName() is only borrowed. In Rust-terms it is similar to fn CFTimeZoneGetName<'a>(&'a CFTimeZoneRef) -> &'a str.

@esheppa
Copy link

esheppa commented Aug 17, 2022

Looks like I'm too spoiled by rust function signatures to have a good understanding of this, but your explanation is excellent!

It looks like we are having to maintain essentially parts of core_foundation::string here - I'm tempted to PR to core-foundation to remove the with_chrono feature as potentially chrono should be providing core-foundation if necessary rather than the other way around.

@esheppa
Copy link

esheppa commented Aug 17, 2022

I've created: servo/core-foundation-rs#521

@lopopolo lopopolo added the Tier-1 Rust Tier-1 platform label Oct 1, 2022
@alex
Copy link

alex commented Oct 11, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Tier-1 Rust Tier-1 platform
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants