Skip to content

Commit ebf55c0

Browse files
authored
Use ios to support ridiculous DL_LOAD_PATH length (#59150)
Use `ios_t` as a string builder for library paths to support really long `DL_LOAD_PATH` entries. `jl_load_dynamic_library` can't use the Julia GC to allocate because we're called from `JuliaOJIT::DLSymOptimizer::lookup` with `symbols_mutex` held. Fixes #59130.
1 parent 21d15ed commit ebf55c0

File tree

1 file changed

+31
-27
lines changed

1 file changed

+31
-27
lines changed

src/dlload.c

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,6 @@ const char *jl_crtdll_name = CRTDLL_BASENAME ".dll";
6868
#undef CRTDLL_BASENAME
6969
#endif
7070

71-
#define PATHBUF 4096
72-
7371
#ifdef _OS_WINDOWS_
7472
void win32_formatmessage(DWORD code, char *reason, int len) JL_NOTSAFEPOINT
7573
{
@@ -272,7 +270,7 @@ void *jl_find_dynamic_library_by_addr(void *symbol, int throw_err) {
272270

273271
JL_DLLEXPORT void *jl_load_dynamic_library(const char *modname, unsigned flags, int throw_err)
274272
{
275-
char path[PATHBUF], relocated[PATHBUF];
273+
ios_t path, relocated;
276274
int i;
277275
#ifdef _OS_WINDOWS_
278276
int err;
@@ -284,7 +282,6 @@ JL_DLLEXPORT void *jl_load_dynamic_library(const char *modname, unsigned flags,
284282
// number of extensions to try — if modname already ends with the
285283
// standard extension, then we don't try adding additional extensions
286284
int n_extensions = endswith_extension(modname) ? 1 : N_EXTENSIONS;
287-
int ret;
288285

289286
// modname == NULL is a sentinel value requesting the handle of libjulia-internal
290287
if (modname == NULL)
@@ -309,6 +306,9 @@ JL_DLLEXPORT void *jl_load_dynamic_library(const char *modname, unsigned flags,
309306
}
310307
#endif
311308

309+
ios_mem(&path, IOS_INLSIZE);
310+
ios_mem(&relocated, IOS_INLSIZE);
311+
312312
/*
313313
this branch permutes all base paths in DL_LOAD_PATH with all extensions
314314
note: skip when !jl_base_module to avoid UndefVarError(:DL_LOAD_PATH),
@@ -325,43 +325,41 @@ JL_DLLEXPORT void *jl_load_dynamic_library(const char *modname, unsigned flags,
325325
size_t j;
326326
for (j = 0; j < jl_array_nrows(DL_LOAD_PATH); j++) {
327327
char *dl_path = jl_string_data(jl_array_ptr_data(DL_LOAD_PATH)[j]);
328-
size_t len = strlen(dl_path);
329-
if (len == 0)
328+
if (*dl_path == 0)
330329
continue;
331330

331+
ios_trunc(&relocated, 0);
332+
332333
// Is this entry supposed to be relative to the bindir?
333-
if (len >= 16 && strncmp(dl_path, "@executable_path", 16) == 0) {
334-
snprintf(relocated, PATHBUF, "%s%s", jl_options.julia_bindir, dl_path + 16);
335-
len = len - 16 + strlen(jl_options.julia_bindir);
334+
if (strncmp(dl_path, "@executable_path", 16) == 0) {
335+
ios_printf(&relocated, "%s%s", jl_options.julia_bindir, dl_path + 16);
336336
} else {
337-
strncpy(relocated, dl_path, PATHBUF);
338-
relocated[PATHBUF-1] = '\0';
337+
ios_puts(dl_path, &relocated);
339338
}
339+
ios_putc(0, &relocated);
340340
for (i = 0; i < n_extensions; i++) {
341+
ios_trunc(&path, 0);
341342
const char *ext = extensions[i];
342-
path[0] = '\0';
343-
if (relocated[len-1] == PATHSEPSTRING[0])
344-
snprintf(path, PATHBUF, "%s%s%s", relocated, modname, ext);
345-
else {
346-
ret = snprintf(path, PATHBUF, "%s" PATHSEPSTRING "%s%s", relocated, modname, ext);
347-
if (ret < 0)
348-
jl_errorf("path is longer than %d\n", PATHBUF);
349-
}
343+
if (relocated.buf[relocated.bpos - 2] == PATHSEPSTRING[0])
344+
ios_printf(&path, "%s%s%s", relocated.buf, modname, ext);
345+
else
346+
ios_printf(&path, "%s" PATHSEPSTRING "%s%s", relocated.buf, modname, ext);
347+
ios_putc(0, &path);
350348

351349
#ifdef _OS_WINDOWS_
352350
if (i == 0) { // LoadLibrary already tested the extensions, we just need to check the `stat` result
353351
#endif
354-
handle = jl_dlopen(path, flags);
352+
handle = jl_dlopen(path.buf, flags);
355353
if (handle && !(flags & JL_RTLD_NOLOAD))
356354
jl_timing_puts(JL_TIMING_DEFAULT_BLOCK, jl_pathname_for_handle(handle));
357355
if (handle)
358-
return handle;
356+
goto success;
359357
#ifdef _OS_WINDOWS_
360358
err = GetLastError();
361359
}
362360
#endif
363361
// bail out and show the error if file actually exists
364-
if (jl_stat(path, (char*)&stbuf) == 0)
362+
if (jl_stat(path.buf, (char*)&stbuf) == 0)
365363
goto notfound;
366364
}
367365
}
@@ -370,20 +368,21 @@ JL_DLLEXPORT void *jl_load_dynamic_library(const char *modname, unsigned flags,
370368

371369
// now fall back and look in default library paths, for all extensions
372370
for (i = 0; i < n_extensions; i++) {
371+
ios_trunc(&path, 0);
373372
const char *ext = extensions[i];
374-
path[0] = '\0';
375-
snprintf(path, PATHBUF, "%s%s", modname, ext);
376-
handle = jl_dlopen(path, flags);
373+
ios_printf(&path, "%s%s", modname, ext);
374+
ios_putc(0, &path);
375+
handle = jl_dlopen(path.buf, flags);
377376
if (handle && !(flags & JL_RTLD_NOLOAD))
378377
jl_timing_puts(JL_TIMING_DEFAULT_BLOCK, jl_pathname_for_handle(handle));
379378
if (handle)
380-
return handle;
379+
goto success;
381380
#ifdef _OS_WINDOWS_
382381
err = GetLastError();
383382
break; // LoadLibrary already tested the rest
384383
#else
385384
// bail out and show the error if file actually exists
386-
if (jl_stat(path, (char*)&stbuf) == 0)
385+
if (jl_stat(path.buf, (char*)&stbuf) == 0)
387386
break;
388387
#endif
389388
}
@@ -396,10 +395,15 @@ JL_DLLEXPORT void *jl_load_dynamic_library(const char *modname, unsigned flags,
396395
#else
397396
const char *reason = dlerror();
398397
#endif
398+
ios_close(&relocated);
399+
ios_close(&path);
399400
jl_errorf("could not load library \"%s\"\n%s", modname, reason);
400401
}
401402
handle = NULL;
402403

404+
success:
405+
ios_close(&relocated);
406+
ios_close(&path);
403407
return handle;
404408
}
405409

0 commit comments

Comments
 (0)