Skip to content

Commit 069861a

Browse files
staticfloatvtjnash
authored andcommitted
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> (cherry picked from commit 76c2431)
1 parent 448072f commit 069861a

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
@@ -166,6 +166,7 @@ JL_DLLEXPORT void *jl_load_dynamic_library(const char *modname, unsigned flags,
166166
uv_stat_t stbuf;
167167
void *handle;
168168
int abspath;
169+
int is_atpath;
169170
// number of extensions to try — if modname already ends with the
170171
// standard extension, then we don't try adding additional extensions
171172
int n_extensions = endswith_extension(modname) ? 1 : N_EXTENSIONS;
@@ -191,16 +192,30 @@ JL_DLLEXPORT void *jl_load_dynamic_library(const char *modname, unsigned flags,
191192
}
192193

193194
abspath = isabspath(modname);
195+
is_atpath = 0;
196+
197+
// Detect if our `modname` is something like `@rpath/libfoo.dylib`
198+
#ifdef _OS_DARWIN_
199+
size_t nameLen = strlen(modname);
200+
const char *const atPaths[] = {"@executable_path/", "@loader_path/", "@rpath/"};
201+
for (i = 0; i < sizeof(atPaths)/sizeof(char*); ++i) {
202+
size_t atLen = strlen(atPaths[i]);
203+
if (nameLen >= atLen && 0 == strncmp(modname, atPaths[i], atLen)) {
204+
is_atpath = 1;
205+
}
206+
}
207+
#endif
194208

195209
/*
196210
this branch permutes all base paths in DL_LOAD_PATH with all extensions
197211
note: skip when !jl_base_module to avoid UndefVarError(:DL_LOAD_PATH),
198212
and also skip for absolute paths
213+
and also skip for `@`-paths on macOS
199214
We also do simple string replacement here for elements starting with `@executable_path/`.
200215
While these exist as OS concepts on Darwin, we want to use them on other platforms
201216
such as Windows, so we emulate them here.
202217
*/
203-
if (!abspath && jl_base_module != NULL) {
218+
if (!abspath && !is_atpath && jl_base_module != NULL) {
204219
jl_binding_t *b = jl_get_module_binding(jl_base_module, jl_symbol("DL_LOAD_PATH"));
205220
jl_array_t *DL_LOAD_PATH = (jl_array_t*)(b ? b->value : NULL);
206221
if (DL_LOAD_PATH != NULL) {

0 commit comments

Comments
 (0)