Skip to content

Commit 76c2431

Browse files
staticfloatvtjnash
andauthored
Disable DL_LOAD_PATH prepending for @-paths on Darwin (#42721)
* Disable `DL_LOAD_PATH` prepending for `@`-paths on Darwin Many thanks to Randy Rucker from Apple for pointing out that we were technically relying on undefined behavior in `dyld` for loading things via `jl_dlopen("@loader_path/@rpath/libfoo.dylib")`, due to the composition of `dlopen("@rpath/libfoo.dylib")` in our Julia code, and the `DL_LOAD_PATH` prepending we do in `jl_load_dynamic_library()`. This PR uses a slightly modified version of a patch emailed to me by Randy, and should solve JuliaLang/Downloads.jl#149 on macOS Monterey where the undefined behavior in `dyld` has changed. * Apply suggestions from code review Co-authored-by: Jameson Nash <vtjnash@gmail.com> * Use `[]` instead of `*` Co-authored-by: Jameson Nash <vtjnash@gmail.com>
1 parent b2d15f0 commit 76c2431

File tree

1 file changed

+16
-1
lines changed

1 file changed

+16
-1
lines changed

src/dlload.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ JL_DLLEXPORT void *jl_load_dynamic_library(const char *modname, unsigned flags,
156156
uv_stat_t stbuf;
157157
void *handle;
158158
int abspath;
159+
int is_atpath;
159160
// number of extensions to try — if modname already ends with the
160161
// standard extension, then we don't try adding additional extensions
161162
int n_extensions = endswith_extension(modname) ? 1 : N_EXTENSIONS;
@@ -181,16 +182,30 @@ JL_DLLEXPORT void *jl_load_dynamic_library(const char *modname, unsigned flags,
181182
}
182183

183184
abspath = jl_isabspath(modname);
185+
is_atpath = 0;
186+
187+
// Detect if our `modname` is something like `@rpath/libfoo.dylib`
188+
#ifdef _OS_DARWIN_
189+
size_t nameLen = strlen(modname);
190+
const char *const atPaths[] = {"@executable_path/", "@loader_path/", "@rpath/"};
191+
for (i = 0; i < sizeof(atPaths)/sizeof(char*); ++i) {
192+
size_t atLen = strlen(atPaths[i]);
193+
if (nameLen >= atLen && 0 == strncmp(modname, atPaths[i], atLen)) {
194+
is_atpath = 1;
195+
}
196+
}
197+
#endif
184198

185199
/*
186200
this branch permutes all base paths in DL_LOAD_PATH with all extensions
187201
note: skip when !jl_base_module to avoid UndefVarError(:DL_LOAD_PATH),
188202
and also skip for absolute paths
203+
and also skip for `@`-paths on macOS
189204
We also do simple string replacement here for elements starting with `@executable_path/`.
190205
While these exist as OS concepts on Darwin, we want to use them on other platforms
191206
such as Windows, so we emulate them here.
192207
*/
193-
if (!abspath && jl_base_module != NULL) {
208+
if (!abspath && !is_atpath && jl_base_module != NULL) {
194209
jl_binding_t *b = jl_get_module_binding(jl_base_module, jl_symbol("DL_LOAD_PATH"));
195210
jl_array_t *DL_LOAD_PATH = (jl_array_t*)(b ? jl_atomic_load_relaxed(&b->value) : NULL);
196211
if (DL_LOAD_PATH != NULL) {

0 commit comments

Comments
 (0)