From c34351c92ae6979ccd549403fe97bc7cc2d1ff5b Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 10 Jun 2025 15:29:18 +0200 Subject: [PATCH] Revert "[lld] check cache before real_path in loadDylib (#140791)" This is causing use-after-frees due to references getting invalidating after the loadedDylibs map grows, see comments on the PR. This reverts commit 475a8a47ead32755bb1377d361afbd1928880e14. --- lld/MachO/DriverUtils.cpp | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/lld/MachO/DriverUtils.cpp b/lld/MachO/DriverUtils.cpp index 0f17ee7804cf..f7f6be049f0e 100644 --- a/lld/MachO/DriverUtils.cpp +++ b/lld/MachO/DriverUtils.cpp @@ -227,7 +227,12 @@ static DenseMap loadedDylibs; DylibFile *macho::loadDylib(MemoryBufferRef mbref, DylibFile *umbrella, bool isBundleLoader, bool explicitlyLinked) { - CachedHashStringRef path(mbref.getBufferIdentifier()); + // Frameworks can be found from different symlink paths, so resolve + // symlinks before looking up in the dylib cache. + SmallString<128> realPath; + std::error_code err = fs::real_path(mbref.getBufferIdentifier(), realPath); + CachedHashStringRef path(!err ? uniqueSaver().save(StringRef(realPath)) + : mbref.getBufferIdentifier()); DylibFile *&file = loadedDylibs[path]; if (file) { if (explicitlyLinked) @@ -235,23 +240,6 @@ DylibFile *macho::loadDylib(MemoryBufferRef mbref, DylibFile *umbrella, return file; } - // Frameworks can be found from different symlink paths, so resolve - // symlinks and look up in the dylib cache. - DylibFile *&realfile = file; - SmallString<128> realPath; - std::error_code err = fs::real_path(mbref.getBufferIdentifier(), realPath); - if (!err) { - CachedHashStringRef resolvedPath(uniqueSaver().save(StringRef(realPath))); - realfile = loadedDylibs[resolvedPath]; - if (realfile) { - if (explicitlyLinked) - realfile->setExplicitlyLinked(); - - file = realfile; - return realfile; - } - } - DylibFile *newFile; file_magic magic = identify_magic(mbref.getBuffer()); if (magic == file_magic::tapi_file) { @@ -263,7 +251,6 @@ DylibFile *macho::loadDylib(MemoryBufferRef mbref, DylibFile *umbrella, } file = make(**result, umbrella, isBundleLoader, explicitlyLinked); - realfile = file; // parseReexports() can recursively call loadDylib(). That's fine since // we wrote the DylibFile we just loaded to the loadDylib cache via the @@ -279,7 +266,6 @@ DylibFile *macho::loadDylib(MemoryBufferRef mbref, DylibFile *umbrella, magic == file_magic::macho_executable || magic == file_magic::macho_bundle); file = make(mbref, umbrella, isBundleLoader, explicitlyLinked); - realfile = file; // parseLoadCommands() can also recursively call loadDylib(). See comment // in previous block for why this means we must copy `file` here.