Pass string error buffer into dln_open

On Windows, the error exists on the stack so we should pass an error
buffer from the caller.
This commit is contained in:
Peter Zhu 2024-04-24 11:01:09 -04:00
Родитель 853c0b1a77
Коммит 057b69cfdf
4 изменённых файлов: 18 добавлений и 17 удалений

25
dln.c
Просмотреть файл

@ -194,7 +194,6 @@ dln_strerror(char *message, size_t size)
}
return message;
}
#define dln_strerror() dln_strerror(message, sizeof message)
#elif defined USE_DLN_DLOPEN
static const char *
dln_strerror(void)
@ -340,14 +339,12 @@ dln_disable_dlclose(void)
#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
void *
dln_open(const char *file, const char **error)
dln_open(const char *file, char *error, size_t size)
{
static const char incompatible[] = "incompatible library version";
void *handle;
#if defined(_WIN32)
char message[1024];
/* Convert the file path to wide char */
WCHAR *winfile = rb_w32_mbstr_to_wstr(CP_UTF8, file, -1, NULL);
if (!winfile) {
@ -359,14 +356,14 @@ dln_open(const char *file, const char **error)
free(winfile);
if (!handle) {
*error = dln_strerror();
strlcpy(error, dln_strerror(error, size), size);
return NULL;
}
# if defined(RUBY_EXPORT)
if (!rb_w32_check_imported(handle, rb_libruby_handle())) {
FreeLibrary(handle);
*error = incompatible;
strlcpy(error, incompatible, size);
return NULL;
}
# endif
@ -386,7 +383,7 @@ dln_open(const char *file, const char **error)
/* Load file */
handle = dlopen(file, RTLD_LAZY|RTLD_GLOBAL);
if (handle == NULL) {
*error = dln_strerror();
strlcpy(error, dln_strerror(), size);
return NULL;
}
@ -409,10 +406,14 @@ dln_open(const char *file, const char **error)
libruby_name = tmp;
}
dlclose(handle);
if (libruby_name) {
dln_loaderror("linked to incompatible %s - %s", libruby_name, file);
snprintf(error, size, "linked to incompatible %s - %s", libruby_name, file);
}
*error = incompatible;
else {
strlcpy(error, incompatible, size);
}
return NULL;
}
}
@ -442,7 +443,7 @@ dln_sym_func(void *handle, const char *symbol)
const char *error;
#if defined(_WIN32)
char message[1024];
error = dln_strerror();
error = dln_strerror(message, sizeof(message));
#elif defined(USE_DLN_DLOPEN)
const size_t errlen = strlen(error = dln_strerror()) + 1;
error = memcpy(ALLOCA_N(char, errlen), error, errlen);
@ -497,8 +498,8 @@ void *
dln_load(const char *file)
{
#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
const char *error = NULL;
void *handle = dln_open(file, &error);
char error[1024];
void *handle = dln_open(file, error, sizeof(error));
if (handle == NULL) {
dln_loaderror("%s - %s", error, file);

2
dln.h
Просмотреть файл

@ -25,7 +25,7 @@ RUBY_SYMBOL_EXPORT_BEGIN
char *dln_find_exe_r(const char*,const char*,char*,size_t DLN_FIND_EXTRA_ARG_DECL);
char *dln_find_file_r(const char*,const char*,char*,size_t DLN_FIND_EXTRA_ARG_DECL);
void *dln_load(const char*);
void *dln_open(const char *file, const char **error);
void *dln_open(const char *file, char *error, size_t size);
void *dln_symbol(void*,const char*);
RUBY_SYMBOL_EXPORT_END

Просмотреть файл

@ -21,9 +21,9 @@ dln_symbol(void *handle, const char *symbol)
UNREACHABLE_RETURN(NULL);
}
NORETURN(void *dln_open(const char *library, const char **error));
NORETURN(void *dln_open(const char *library, char *error, size_t size));
void*
dln_open(const char *library, const char **error)
dln_open(const char *library, char *error, size_t size)
{
rb_loaderror("this executable file can't load extension libraries");

4
gc.c
Просмотреть файл

@ -1896,8 +1896,8 @@ ruby_external_gc_init()
char *gc_so_path = getenv("RUBY_GC_LIBRARY_PATH");
void *handle = NULL;
if (gc_so_path) {
const char *error = NULL;
handle = dln_open(gc_so_path, &error);
char error[128];
handle = dln_open(gc_so_path, error, sizeof(error));
if (!handle) {
rb_bug("ruby_external_gc_init: Shared library %s cannot be opened (%s)", gc_so_path, error);
}