Skip to content

Commit 81a409f

Browse files
committed
Fixed coverity in acl_hal_mmd.cpp: Resource leak (RESOURCE_LEAK)
mmd_libraries were not closed after execution, which causes memory leaks. But mmd_libraries cannot be closed trivially since closing the library invalidates the symbol return by dlsym(), which means calling the function further down is undefined behaviour. To solve this issues, I added a `dl_wrapper_t` vector as a global initialized vector that would be deallocated when closing the runtime library. This vector would contain all the opened libraries that would be closed by the destructor of `dl_wrapper_t` once the vector deallocates.
1 parent 71d527e commit 81a409f

File tree

1 file changed

+50
-14
lines changed

1 file changed

+50
-14
lines changed

src/acl_hal_mmd.cpp

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,40 @@ unsigned acl_convert_mmd_capabilities(unsigned mmd_capabilities);
188188
const static size_t MIN_SOF_SIZE = 1;
189189
const static size_t MIN_PLL_CONFIG_SIZE = 1;
190190

191+
// Helper function needed for dl libraries wrapper
192+
void *my_dlopen(const char *library_name, char **error_msg);
193+
void *my_dlsym(void *library, const char *function_name, char **error_msg);
194+
195+
// Wrapper for dl libraries
196+
struct dl_wrapper_t {
197+
void *mmd_lib;
198+
dl_wrapper_t(const char *library_name, char **error_msg) {
199+
this->mmd_lib = my_dlopen(library_name, error_msg);
200+
}
201+
~dl_wrapper_t() {
202+
if (this->mmd_lib) {
203+
#ifdef _WIN32
204+
FreeLibrary((HMODULE)this->mmd_lib);
205+
#else
206+
dlclose(this->mmd_lib);
207+
#endif
208+
}
209+
}
210+
// prohibit copying to avoid double-close of handle
211+
dl_wrapper_t(const dl_wrapper_t &) = delete;
212+
dl_wrapper_t &operator=(const dl_wrapper_t &) = delete;
213+
214+
// enable move for vector operations
215+
dl_wrapper_t(dl_wrapper_t &&) noexcept {};
216+
217+
// return symbol
218+
void *sym(const char *function_name, char **error_msg) {
219+
return my_dlsym(this->mmd_lib, function_name, error_msg);
220+
}
221+
};
222+
191223
std::vector<acl_mmd_dispatch_t> internal_mmd_dispatch;
224+
std::vector<dl_wrapper_t> dl_wrapper_list;
192225

193226
// Dynamically load board mmd & symbols
194227
static size_t num_board_pkgs;
@@ -568,8 +601,9 @@ cl_bool l_load_single_board_library(const char *library_name,
568601
return CL_FALSE;
569602
}
570603
#endif
571-
auto *mmd_library = my_dlopen(library_name, &error_msg);
572-
if (!mmd_library) {
604+
dl_wrapper_list.emplace_back(library_name, &error_msg);
605+
if (!dl_wrapper_list.back().mmd_lib) {
606+
dl_wrapper_list.pop_back();
573607
std::cout << "Error: Could not load board library " << library_name;
574608
if (error_msg && error_msg[0] != '\0') {
575609
std::cout << " (error_msg: " << error_msg << ")";
@@ -579,17 +613,18 @@ cl_bool l_load_single_board_library(const char *library_name,
579613
}
580614

581615
auto *test_symbol =
582-
my_dlsym(mmd_library, "aocl_mmd_get_offline_info", &error_msg);
616+
dl_wrapper_list.back().sym("aocl_mmd_get_offline_info", &error_msg);
583617
if (!test_symbol) {
584618
// On Linux, for custom libraries close the library (which was opened
585619
// locally) and then reopen globally. For Windows, there is no option (i.e.
586620
// it is always global)
587621
#ifdef __linux__
588-
my_dlclose(mmd_library);
622+
my_dlclose(dl_wrapper_list.back().mmd_lib);
589623
ACL_HAL_DEBUG_MSG_VERBOSE(
590624
1, "This library is a custom library. Opening globally.\n");
591-
mmd_library = my_dlopen_global(library_name, &error_msg);
592-
if (!mmd_library) {
625+
dl_wrapper_list.back().mmd_lib = my_dlopen_global(library_name, &error_msg);
626+
if (!dl_wrapper_list.back().mmd_lib) {
627+
dl_wrapper_list.pop_back();
593628
std::cout << "Error: Could not load custom library " << library_name;
594629
if (error_msg && error_msg[0] != '\0') {
595630
std::cout << " (error_msg: " << error_msg << ")";
@@ -600,9 +635,9 @@ cl_bool l_load_single_board_library(const char *library_name,
600635
#endif
601636
} else {
602637
if (load_libraries) {
603-
auto result =
604-
l_load_board_functions(&(internal_mmd_dispatch[num_boards_found]),
605-
library_name, mmd_library, error_msg);
638+
auto result = l_load_board_functions(
639+
&(internal_mmd_dispatch[num_boards_found]), library_name,
640+
dl_wrapper_list.back().mmd_lib, error_msg);
606641
if (result == CL_FALSE) {
607642
std::cout << "Error: Could not load board library " << library_name
608643
<< " due to failure to load symbols\n";
@@ -855,6 +890,7 @@ cl_bool l_load_board_libraries(cl_bool load_libraries) {
855890
}
856891
fin.close();
857892
}
893+
closedir(dir);
858894
}
859895

860896
if (num_vendor_files_found == 0) {
@@ -876,8 +912,6 @@ cl_bool l_load_board_libraries(cl_bool load_libraries) {
876912
}
877913
}
878914

879-
if (dir)
880-
closedir(dir);
881915
return num_boards_found == 0 ? CL_FALSE : CL_TRUE;
882916
}
883917
#endif
@@ -1156,9 +1190,10 @@ static acl_mmd_dispatch_t *get_msim_mmd_layer() {
11561190
ipa_simulator ? mmd_lib_name_ipa : mmd_lib_name_aoc;
11571191

11581192
char *error_msg = nullptr;
1159-
auto *mmd_lib = my_dlopen(mmd_lib_name, &error_msg);
1193+
dl_wrapper_list.emplace_back(mmd_lib_name, &error_msg);
11601194
typedef acl_mmd_dispatch_t *(*fcn_type)();
1161-
if (!mmd_lib) {
1195+
if (!dl_wrapper_list.back().mmd_lib) {
1196+
dl_wrapper_list.pop_back();
11621197
std::cout << "Error: Could not load simulation MMD library "
11631198
<< mmd_lib_name;
11641199
if (error_msg && error_msg[0] != '\0') {
@@ -1167,8 +1202,9 @@ static acl_mmd_dispatch_t *get_msim_mmd_layer() {
11671202
std::cout << "\n";
11681203
return nullptr;
11691204
}
1170-
auto *sym = my_dlsym(mmd_lib, sym_name, &error_msg);
1205+
auto *sym = dl_wrapper_list.back().sym(sym_name, &error_msg);
11711206
if (!sym) {
1207+
dl_wrapper_list.pop_back();
11721208
std::cout << "Error: Symbol " << sym_name
11731209
<< " not found in simulation MMD library ";
11741210
if (error_msg && error_msg[0] != '\0') {

0 commit comments

Comments
 (0)