diff --git a/src/ccall.cpp b/src/ccall.cpp index 65c0fa74c9ace8..ac59279a8a8255 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -5,6 +5,10 @@ #include #include +#ifdef _OS_WINDOWS_ +extern const char jl_crtdll_basename[]; +#endif + // somewhat unusual variable, in that aotcompile wants to get the address of this for a sanity check GlobalVariable *jl_emit_RTLD_DEFAULT_var(Module *M) { @@ -1266,7 +1270,20 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) auto _is_libjulia_func = [&] (uintptr_t ptr, const char *name) { if ((uintptr_t)fptr == ptr) return true; - return (!f_lib || f_lib == JL_LIBJULIA_INTERNAL_DL_LIBNAME) && f_name && !strcmp(f_name, name); + if (f_lib) { +#ifdef _OS_WINDOWS_ + if ((f_lib == JL_EXE_LIBNAME) || // preventing invalid pointer access + (f_lib == JL_LIBJULIA_INTERNAL_DL_LIBNAME) || + (!strcmp(f_lib, jl_crtdll_basename))) { + // libjulia-like + } + else + return false; +#else + return false; +#endif + } + return f_name && !strcmp(f_name, name); }; #define is_libjulia_func(name) _is_libjulia_func((uintptr_t)&(name), #name) diff --git a/src/dlload.c b/src/dlload.c index 22017708515dbd..ecb34d2be57e33 100644 --- a/src/dlload.c +++ b/src/dlload.c @@ -57,6 +57,25 @@ static int endswith_extension(const char *path) JL_NOTSAFEPOINT return 0; } +#ifdef _OS_WINDOWS_ +#ifdef _MSC_VER +#if (_MSC_VER >= 1930) || (_MSC_VER < 1800) +#error This version of MSVC has not been tested. +#elif _MSC_VER >= 1900 // VC++ 2015 / 2017 / 2019 +#define CRTDLL_BASENAME "vcruntime140" +#elif _MSC_VER >= 1800 // VC++ 2013 +#define CRTDLL_BASENAME "msvcr120" +#endif +#else +#define CRTDLL_BASENAME "msvcrt" +#endif + +const char jl_crtdll_basename[] = CRTDLL_BASENAME; +const char jl_crtdll_name[] = CRTDLL_BASENAME ".dll"; + +#undef CRTDLL_BASENAME +#endif + #define PATHBUF 4096 #define JL_RTLD(flags, FLAG) (flags & JL_RTLD_ ## FLAG ? RTLD_ ## FLAG : 0) @@ -314,18 +333,10 @@ const char *jl_dlfind_win32(const char *f_name) return JL_LIBJULIA_DL_LIBNAME; if (jl_dlsym(jl_kernel32_handle, f_name, &dummy, 0)) return "kernel32"; + if (jl_dlsym(jl_crtdll_handle, f_name, &dummy, 0)) // Prefer crtdll over ntdll + return jl_crtdll_basename; if (jl_dlsym(jl_ntdll_handle, f_name, &dummy, 0)) return "ntdll"; - if (jl_dlsym(jl_crtdll_handle, f_name, &dummy, 0)) -#if defined(_MSC_VER) -#if _MSC_VER == 1800 - return "msvcr120"; -#else -#error This version of MSVC has not been tested. -#endif -#else - return "msvcrt"; -#endif if (jl_dlsym(jl_winsock_handle, f_name, &dummy, 0)) return "ws2_32"; // additional common libraries (libc?) could be added here, but in general, diff --git a/src/init.c b/src/init.c index 45c293c8873c0f..f66403c58199c0 100644 --- a/src/init.c +++ b/src/init.c @@ -302,6 +302,7 @@ void *jl_ntdll_handle; void *jl_kernel32_handle; void *jl_crtdll_handle; void *jl_winsock_handle; +extern const char jl_crtdll_name[]; #endif uv_loop_t *jl_io_loop; @@ -665,11 +666,7 @@ void _julia_init(JL_IMAGE_SEARCH rel) #ifdef _OS_WINDOWS_ jl_ntdll_handle = jl_dlopen("ntdll.dll", 0); // bypass julia's pathchecking for system dlls jl_kernel32_handle = jl_dlopen("kernel32.dll", 0); -#if defined(_MSC_VER) && _MSC_VER == 1800 - jl_crtdll_handle = jl_dlopen("msvcr120.dll", 0); -#else - jl_crtdll_handle = jl_dlopen("msvcrt.dll", 0); -#endif + jl_crtdll_handle = jl_dlopen(jl_crtdll_name, 0); jl_winsock_handle = jl_dlopen("ws2_32.dll", 0); jl_exe_handle = GetModuleHandleA(NULL); JL_MUTEX_INIT(&jl_in_stackwalk); diff --git a/test/ccall.jl b/test/ccall.jl index c8484579929e17..c81d2945f5c745 100644 --- a/test/ccall.jl +++ b/test/ccall.jl @@ -1576,6 +1576,19 @@ let @test arr[1] == '0' end +# issue #38751 +let + function f38751!(dest::Vector{UInt8}, src::Vector{UInt8}, n::UInt) + d, s = pointer(dest), pointer(src) + GC.@preserve dest src ccall(:memcpy, Cvoid, (Ptr{UInt8}, Ptr{UInt8}, Csize_t), d, s, n) + return dest + end + dest = zeros(UInt8, 8) + @test f38751!(dest, collect(0x1:0x8), UInt(8)) == 0x1:0x8 + llvm = sprint(code_llvm, f38751!, (Vector{UInt8}, Vector{UInt8}, UInt)) + @test !occursin("call void inttoptr", llvm) +end + # issue #34061 let o_file = tempname(), err = Base.PipeEndpoint() run(pipeline(Cmd(`$(Base.julia_cmd()) --output-o=$o_file -e 'Base.reinit_stdio();