11/*
2- Copyright (c) 2005-2024 Intel Corporation
2+ Copyright (c) 2005-2025 Intel Corporation
33
44 Licensed under the Apache License, Version 2.0 (the "License");
55 you may not use this file except in compliance with the License.
2121#define _CRT_SECURE_NO_WARNINGS
2222#endif
2323
24+ #define __TBB_NO_IMPLICIT_LINKAGE 1
25+
2426#include " common/test.h"
2527
28+ // Out-of-line TBB assertion handling routines are instantiated here
29+ #include " ../../src/tbb/assert_impl.h"
30+
2631enum FOO_TYPE {
2732 FOO_DUMMY,
2833 FOO_IMPLEMENTATION
@@ -42,31 +47,43 @@ FOO_TYPE dummy_foo1() { return FOO_DUMMY; }
4247FOO_TYPE dummy_foo2 () { return FOO_DUMMY; }
4348
4449#include " oneapi/tbb/detail/_config.h"
50+ #include " oneapi/tbb/version.h"
51+
4552// Suppress the weak symbol mechanism to avoid surplus compiler warnings.
4653#ifdef __TBB_WEAK_SYMBOLS_PRESENT
4754#undef __TBB_WEAK_SYMBOLS_PRESENT
4855#endif
49- #include " src/tbb/dynamic_link.h"
5056
51- #if __TBB_DYNAMIC_LOAD_ENABLED
52- // Handlers.
53- static FOO_TYPE (*foo1_handler)() = &dummy_foo1;
54- static FOO_TYPE (*foo2_handler)() = &dummy_foo2;
55-
56- // Table describing how to link the handlers.
57- static const tbb::detail::r1::dynamic_link_descriptor LinkTable[] = {
58- { " foo1" , (tbb::detail::r1::pointer_to_handler*)(void *)(&foo1_handler) },
59- { " foo2" , (tbb::detail::r1::pointer_to_handler*)(void *)(&foo2_handler) }
60- };
61- #endif
6257
63- // The direct include since we want to test internal functionality.
58+ #ifndef TBB_DYNAMIC_LINK_WARNING
59+ #define TBB_DYNAMIC_LINK_WARNING 1
60+ #endif
61+ #ifdef __TBB_SKIP_DEPENDENCY_SIGNATURE_VERIFICATION
62+ #warning "Signature verification must not be turned off to fully test dynamic link functionality"
63+ #endif
64+ // The direct include since we want to test internal functionality
6465#include " src/tbb/dynamic_link.cpp"
66+
67+
6568#include " common/utils.h"
6669#include " common/utils_dynamic_libs.h"
6770
71+ #include < cstdio> // for std::snprintf
72+ #include < cstring> // for std::strcmp
73+
6874void test_dynamic_link (const char * lib_name) {
6975#if __TBB_DYNAMIC_LOAD_ENABLED
76+ // Handlers.
77+ static FOO_TYPE (*foo1_handler)() = nullptr ;
78+ static FOO_TYPE (*foo2_handler)() = nullptr ;
79+ foo1_handler = &dummy_foo1;
80+ foo2_handler = &dummy_foo2;
81+
82+ // Table describing how to link the handlers.
83+ static const tbb::detail::r1::dynamic_link_descriptor LinkTable[] = {
84+ { " foo1" , (tbb::detail::r1::pointer_to_handler*)(void *)(&foo1_handler) },
85+ { " foo2" , (tbb::detail::r1::pointer_to_handler*)(void *)(&foo2_handler) }
86+ };
7087#if !_WIN32
7188 // Check if the executable exports its symbols.
7289 REQUIRE_MESSAGE ((utils::GetAddress (utils::OpenLibrary (nullptr ), " foo1" ) && utils::GetAddress (utils::OpenLibrary (nullptr ), " foo2" )),
@@ -80,9 +97,10 @@ void test_dynamic_link(const char* lib_name) {
8097 if (tbb::detail::r1::dynamic_link (lib_name, LinkTable, sizeof (LinkTable) / sizeof (LinkTable[0 ]))) {
8198 REQUIRE_MESSAGE ((foo1_handler && foo2_handler), " The symbols are corrupted by dynamic_link" );
8299 REQUIRE_MESSAGE ((foo1_handler () == FOO_IMPLEMENTATION && foo2_handler () == FOO_IMPLEMENTATION),
83- " dynamic_link returned the successful code but symbol(s) are wrong" );
100+ " dynamic_link returned the successful code but symbol(s) are wrong" );
84101 } else {
85- REQUIRE_MESSAGE ((foo1_handler == dummy_foo1 && foo2_handler == dummy_foo2), " The symbols are corrupted by dynamic_link" );
102+ REQUIRE_MESSAGE ((foo1_handler == &dummy_foo1 && foo2_handler == &dummy_foo2),
103+ " The symbols are corrupted by dynamic_link" );
86104 }
87105#else
88106 utils::suppress_unused_warning (lib_name);
@@ -97,6 +115,92 @@ TEST_CASE("Test dynamic_link with non-existing library") {
97115
98116// ! Testing dynamic_link
99117// ! \brief \ref error_guessing
100- TEST_CASE (" Test dynamic_link" ) {
118+ TEST_CASE (" Test dynamic_link corner cases" ) {
119+ test_dynamic_link (nullptr );
101120 test_dynamic_link (" " );
102121}
122+
123+
124+ #if __TBB_DYNAMIC_LOAD_ENABLED
125+
126+ #if !__TBB_WIN8UI_SUPPORT
127+ // ! Testing dynamic_link with existing library
128+ // ! \brief \ref requirement
129+ TEST_CASE (" Test dynamic_link with existing library" ) {
130+ // Check that not-yet-linked library is found and loaded even without specifying absolute path to
131+ // it. On Windows, signature validation is performed in addition.
132+ #if _WIN32
133+ // Well known signed Windows library that exist in every distribution
134+ const char * lib_name = " user32.dll" ;
135+ const char * symbol = " MessageBoxA" ;
136+ int (*handler)(void * /* hWnd*/ , const char * /* lpText*/ , const char * /* lpCaption*/ ,
137+ unsigned int /* uType*/ ) = nullptr ;
138+ #else
139+ const char * lib_name = TBBLIB_NAME; // On Linux it is the name of the library itself
140+ const char * symbol = " TBB_runtime_version" ;
141+ static const char * (*handler)() = nullptr ;
142+ #endif
143+ static const tbb::detail::r1::dynamic_link_descriptor table[] = {
144+ { symbol, (tbb::detail::r1::pointer_to_handler*)(void *)(&handler) },
145+ };
146+
147+ constexpr int load_flags =
148+ tbb::detail::r1::DYNAMIC_LINK_DEFAULT & ~tbb::detail::r1::DYNAMIC_LINK_BUILD_ABSOLUTE_PATH;
149+ const bool link_result = tbb::detail::r1::dynamic_link (lib_name, table,
150+ sizeof (table) / sizeof (table[0 ]),
151+ /* handle*/ nullptr , load_flags);
152+ char msg[128 ] = {0 };
153+ std::snprintf (msg, sizeof (msg) / sizeof (msg[0 ]), " The library \" %s\" was not loaded" , lib_name);
154+ REQUIRE_MESSAGE (link_result, msg);
155+ REQUIRE_MESSAGE (handler, " The symbol was not found." );
156+ #if !_WIN32
157+ REQUIRE_MESSAGE (0 == std::strcmp (handler (), TBB_VERSION_STRING),
158+ " dynamic_link returned successful code but symbol returned incorrect result" );
159+ #endif
160+ }
161+ #endif // !__TBB_WIN8UI_SUPPORT
162+
163+ // ! Testing dynamic_link with stub library known to be unsigned (on Windows) and having no exported
164+ // ! symbols (on Linux)
165+ // \brief \ref requirement
166+ TEST_CASE (" Test dynamic_link with bad library" ) {
167+ const int size = PATH_MAX + 1 ;
168+ const char * lib_name = TEST_LIBRARY_NAME (" stub_unsigned" );
169+ char path[size] = {0 };
170+ const int msg_size = size + 128 ; // Path to the file + message
171+ char msg[msg_size] = {0 };
172+
173+ #if !__TBB_WIN8UI_SUPPORT
174+ const std::size_t len = tbb::detail::r1::abs_path (lib_name, path, sizeof (path));
175+ REQUIRE_MESSAGE ((0 < len && len <= PATH_MAX), " The path to the library is not built" );
176+ std::snprintf (msg, msg_size, " Test prerequisite is not held - the path \" %s\" must exist" , path);
177+ REQUIRE_MESSAGE (tbb::detail::r1::file_exists (path), msg);
178+ #endif
179+
180+ // The library exists, check that it will not be loaded.
181+ void (*handler)() = nullptr ;
182+ static const tbb::detail::r1::dynamic_link_descriptor table[] = {
183+ { " foo" , (tbb::detail::r1::pointer_to_handler*)(void *)(&handler) },
184+ };
185+
186+ // Specify library name without absolute path to test that it still can be found because it
187+ // resides in the application (i.e. test) directory
188+ constexpr int load_flags =
189+ tbb::detail::r1::DYNAMIC_LINK_DEFAULT & ~tbb::detail::r1::DYNAMIC_LINK_BUILD_ABSOLUTE_PATH;
190+ const bool link_result = tbb::detail::r1::dynamic_link (lib_name, table,
191+ sizeof (table) / sizeof (table[0 ]),
192+ /* handle*/ nullptr , load_flags);
193+ std::snprintf (msg, msg_size, " The library \" %s\" was loaded but should not have been." , path);
194+
195+ // Expectation is that the library will not be loaded because:
196+ // a) On Windows the library is unsigned
197+ // b) On Linux the library does not have exported symbols
198+ const bool expected_link_result = false ;
199+
200+ REQUIRE_MESSAGE (expected_link_result == link_result, msg);
201+ REQUIRE_MESSAGE (nullptr == handler, " The symbol should not be changed." );
202+ // TODO: Verify the warning message contains "TBB dynamic link warning: The module
203+ // \".*stub_unsigned.*.dll\" is unsigned or has invalid signature."
204+ }
205+
206+ #endif // __TBB_DYNAMIC_LOAD_ENABLED
0 commit comments