diff --git a/libclamav/others.c b/libclamav/others.c index 2b9fc6f1c7..bf226284e0 100644 --- a/libclamav/others.c +++ b/libclamav/others.c @@ -96,99 +96,91 @@ static void *load_module(const char *name, const char *featurename) { #ifdef _WIN32 static const char *suffixes[] = {LT_MODULE_EXT}; + HMODULE rhandle = NULL; #else static const char *suffixes[] = { LT_MODULE_EXT "." LIBCLAMAV_FULLVER, PASTE(LT_MODULE_EXT ".", LIBCLAMAV_MAJORVER), LT_MODULE_EXT, "." LT_LIBEXT}; + void *rhandle = NULL; + char *tokenized_library_path = NULL; + char *ld_library_path = NULL; + const char *searchpath; #endif - const char *searchpath; char modulename[128]; size_t i; -#ifdef _WIN32 - HMODULE rhandle = NULL; -#else - void *rhandle; -#endif + +#ifndef _WIN32 + /* + * First try using LD_LIBRARY_PATH environment variable for the path. + * We do this first because LD_LIBRARY_PATH is intended as an option to override the installed library path. + * + * We don't do this for Windows because Windows doesn't have an equivalent to LD_LIBRARY_PATH + * and because LoadLibraryA() will search the executable's folder, which works for the unit tests. + */ + ld_library_path = getenv("LD_LIBRARY_PATH"); + if (NULL != ld_library_path && strlen(ld_library_path) > 0) { +#define MAX_LIBRARY_PATHS 10 + size_t token_index; + size_t tokens_count; + const char *tokens[MAX_LIBRARY_PATHS]; + + /* + * LD_LIBRARY_PATH may be a colon-separated list of directories. + * Tokenize the list and try to load the library from each directory. + */ + tokenized_library_path = strdup(ld_library_path); + tokens_count = cli_strtokenize(tokenized_library_path, ':', MAX_LIBRARY_PATHS, tokens); + + for (token_index = 0; token_index < tokens_count; token_index++) { + cli_dbgmsg("searching for %s, LD_LIBRARY_PATH: %s\n", featurename, tokens[token_index]); + + for (i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); i++) { + snprintf(modulename, sizeof(modulename), "%s" PATHSEP "%s%s", tokens[token_index], name, suffixes[i]); + + rhandle = dlopen(modulename, RTLD_NOW); + if (NULL != rhandle) { + goto done; + } + cli_dbgmsg("searching for %s: %s not found\n", featurename, modulename); + } + } + } +#endif // !_WIN32 #ifdef _WIN32 /* - * First try a standard LoadLibraryA() without specifying a full path. + * For Windows, just try a standard LoadLibraryA() with each of the different possible suffixes. * For more information on the DLL search order, see: - * https://docs.microsoft.com/en-us/windows/desktop/Dlls/dynamic-link-library-search-order + * https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order */ cli_dbgmsg("searching for %s\n", featurename); + + for (i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); i++) { + snprintf(modulename, sizeof(modulename), "%s%s", name, suffixes[i]); + rhandle = LoadLibraryA(modulename); #else /* - * First search using the provided SEARCH_LIBDIR (e.g. "/lib") - * Known issue: If an older clamav version is already installed, the clamav - * unit tests using this function will load the older library version from - * the install path first. + * Search in "/lib" checking with each of the different possible suffixes. */ searchpath = SEARCH_LIBDIR; cli_dbgmsg("searching for %s, user-searchpath: %s\n", featurename, searchpath); -#endif for (i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); i++) { -#ifdef _WIN32 - snprintf(modulename, sizeof(modulename), "%s%s", name, suffixes[i]); - rhandle = LoadLibraryA(modulename); -#else // !_WIN32 snprintf(modulename, sizeof(modulename), "%s" PATHSEP "%s%s", searchpath, name, suffixes[i]); - rhandle = dlopen(modulename, RTLD_NOW); -#endif // !_WIN32 - if (rhandle) { - break; + rhandle = dlopen(modulename, RTLD_NOW); +#endif + if (NULL != rhandle) { + goto done; } - cli_dbgmsg("searching for %s: %s not found\n", featurename, modulename); } - if (NULL == rhandle) { - char *ld_library_path = NULL; - /* - * library not found. - * Try again using LD_LIBRARY_PATH environment variable for the path. - */ - ld_library_path = getenv("LD_LIBRARY_PATH"); - if (NULL != ld_library_path) { -#define MAX_LIBRARY_PATHS 10 - size_t token_index; - size_t tokens_count; - const char *tokens[MAX_LIBRARY_PATHS]; - - char *tokenized_library_path = NULL; - - tokenized_library_path = strdup(ld_library_path); - tokens_count = cli_strtokenize(tokenized_library_path, ':', MAX_LIBRARY_PATHS, tokens); - - for (token_index = 0; token_index < tokens_count; token_index++) { - cli_dbgmsg("searching for %s, LD_LIBRARY_PATH: %s\n", featurename, tokens[token_index]); - - for (i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); i++) { - snprintf(modulename, sizeof(modulename), "%s" PATHSEP "%s%s", tokens[token_index], name, suffixes[i]); -#ifdef _WIN32 - rhandle = LoadLibraryA(modulename); -#else // !_WIN32 - rhandle = dlopen(modulename, RTLD_NOW); -#endif // !_WIN32 - if (rhandle) { - break; - } - - cli_dbgmsg("searching for %s: %s not found\n", featurename, modulename); - } - - if (rhandle) { - break; - } - } - free(tokenized_library_path); - } - } + cli_dbgmsg("%s support loaded from %s\n", featurename, modulename); +done: if (NULL == rhandle) { #ifdef _WIN32 char *err = NULL; @@ -207,29 +199,23 @@ static void *load_module(const char *name, const char *featurename) const char *err = dlerror(); #endif // !_WIN32 -#ifdef WARN_DLOPEN_FAIL - if (NULL == err) { - cli_warnmsg("Cannot dlopen %s: Unknown error - %s support unavailable\n", name, featurename); - } else { - cli_warnmsg("Cannot dlopen %s: %s - %s support unavailable\n", name, err, featurename); - } -#else if (NULL == err) { cli_dbgmsg("Cannot dlopen %s: Unknown error - %s support unavailable\n", name, featurename); } else { cli_dbgmsg("Cannot dlopen %s: %s - %s support unavailable\n", name, err, featurename); } -#endif #ifdef _WIN32 if (NULL != err) { LocalFree(err); } #endif - return rhandle; } - cli_dbgmsg("%s support loaded from %s\n", featurename, modulename); +#ifndef _WIN32 + free(tokenized_library_path); +#endif + return (void *)rhandle; } diff --git a/libclamunrar/CMakeLists.txt b/libclamunrar/CMakeLists.txt index ffc09c9bd5..2500a42fa9 100644 --- a/libclamunrar/CMakeLists.txt +++ b/libclamunrar/CMakeLists.txt @@ -1,7 +1,6 @@ # Copyright (C) 2019-2024 Cisco Systems, Inc. and/or its affiliates. All rights reserved. add_compile_definitions(RARDLL) -add_compile_definitions(WARN_DLOPEN_FAIL) add_compile_definitions(_FILE_OFFSET_BITS=64) if(WIN32)