Skip to content

Commit 3ae03a7

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 ace918f commit 3ae03a7

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
@@ -163,6 +163,7 @@ JL_DLLEXPORT void *jl_load_dynamic_library(const char *modname, unsigned flags,
163163
uv_stat_t stbuf;
164164
void *handle;
165165
int abspath;
166+
int is_atpath;
166167
// number of extensions to try — if modname already ends with the
167168
// standard extension, then we don't try adding additional extensions
168169
int n_extensions = endswith_extension(modname) ? 1 : N_EXTENSIONS;
@@ -188,16 +189,30 @@ JL_DLLEXPORT void *jl_load_dynamic_library(const char *modname, unsigned flags,
188189
}
189190

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

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

0 commit comments

Comments
 (0)