diff --git a/src/tbb/cgroup_info.h b/src/tbb/cgroup_info.h index b8039fe3c6..1fa5b28295 100644 --- a/src/tbb/cgroup_info.h +++ b/src/tbb/cgroup_info.h @@ -149,11 +149,12 @@ class cgroup_info { } static bool try_read_cgroup_v1_num_cpus_from(const char* dir, int& num_cpus) { - char path[PATH_MAX] = {0}; - if (std::snprintf(path, PATH_MAX, "%s/cpu.cfs_quota_us", dir) < 0) + std::size_t pathlen = strlen(dir) + 30; + std::unique_ptr path(new char[pathlen]); + if (std::snprintf(path.get(), pathlen, "%s/cpu.cfs_quota_us", dir) < 0) return false; // Failed to create path - unique_file_t fd(std::fopen(path, "r"), &close_file); + unique_file_t fd(std::fopen(path.get(), "r"), &close_file); if (!fd) return false; @@ -166,9 +167,10 @@ class cgroup_info { return true; } - if (std::snprintf(path, PATH_MAX, "%s/cpu.cfs_period_us", dir) < 0) + if (std::snprintf(path.get(), pathlen, "%s/cpu.cfs_period_us", dir) < 0) return false; // Failed to create path; - fd.reset(std::fopen(path, "r")); + + fd.reset(std::fopen(path.get(), "r")); if (!fd) return false; @@ -181,11 +183,12 @@ class cgroup_info { } static bool try_read_cgroup_v2_num_cpus_from(const char* dir, int& num_cpus) { - char path[PATH_MAX] = {0}; - if (std::snprintf(path, PATH_MAX, "%s/cpu.max", dir) < 0) + std::size_t pathlen = strlen(dir) + 30; + std::unique_ptr path(new char[pathlen]); + if (std::snprintf(path.get(), pathlen, "%s/cpu.max", dir) < 0) return false; // Failed to create path - unique_file_t fd(std::fopen(path, "r"), &close_file); + unique_file_t fd(std::fopen(path.get(), "r"), &close_file); if (!fd) return false; @@ -222,9 +225,10 @@ class cgroup_info { static int parse_cgroup_entry(const char* mnt_dir, process_cgroup_data& pcd) { int num_cpus = error_value; // Initialize to an impossible value - char dir[PATH_MAX] = {0}; - if (std::snprintf(dir, PATH_MAX, "%s/%s", mnt_dir, pcd.relative_path) >= 0) { - if (try_read_cgroup_num_cpus_from(dir, num_cpus, pcd.version)) { + std::size_t dirlen = strlen(mnt_dir) + strlen(pcd.relative_path) + 2; + std::unique_ptr dir(new char[dirlen]); + if (std::snprintf(dir.get(), dirlen, "%s/%s", mnt_dir, pcd.relative_path) >= 0) { + if (try_read_cgroup_num_cpus_from(dir.get(), num_cpus, pcd.version)) { return num_cpus; } } @@ -276,16 +280,20 @@ class cgroup_info { static int try_common_cgroup_mount_path(const process_cgroup_data& pcd, const cgroup_settings& cg_cfg) { int num_cpus = error_value; - char dir[PATH_MAX] = {0}; + std::size_t dirlen = (strlen(pcd.relative_path) + + strlen(cg_cfg.sys_fs_cgroup_dir_path) + + 25); + std::unique_ptr dir(new char[dirlen]); __TBB_ASSERT(*pcd.relative_path, nullptr); - if (0 <= std::snprintf(dir, PATH_MAX, "%s/%s", cg_cfg.sys_fs_cgroup_dir_path, + if (0 <= std::snprintf(dir.get(), dirlen, "%s/%s", + cg_cfg.sys_fs_cgroup_dir_path, pcd.relative_path)) - try_read_cgroup_num_cpus_from(dir, num_cpus, pcd.version); + try_read_cgroup_num_cpus_from(dir.get(), num_cpus, pcd.version); if (error_value == num_cpus && pcd.version == process_cgroup_data::cgroup_version::v2) { - if (0 <= std::snprintf(dir, PATH_MAX, "%s/%s", "/sys/fs/cgroup/unified", + if (0 <= std::snprintf(dir.get(), dirlen, "%s/%s", "/sys/fs/cgroup/unified", pcd.relative_path)) - try_read_cgroup_v2_num_cpus_from(dir, num_cpus); + try_read_cgroup_v2_num_cpus_from(dir.get(), num_cpus); } return num_cpus; } diff --git a/src/tbb/dynamic_link.cpp b/src/tbb/dynamic_link.cpp index 868bb96c5e..19593abc1c 100644 --- a/src/tbb/dynamic_link.cpp +++ b/src/tbb/dynamic_link.cpp @@ -45,9 +45,6 @@ #include #pragma comment (lib, "wintrust") // Link with the Wintrust.lib file. #endif -#ifndef PATH_MAX - #define PATH_MAX MAX_PATH -#endif #else /* _WIN32 */ #include #include @@ -177,7 +174,7 @@ namespace r1 { break; case dl_buff_too_small: TBB_FPRINTF(stderr, "%s An internal buffer representing a path to dynamically loaded " - "module is small. Consider compiling with larger value for PATH_MAX macro.\n", + "module is small.\n", prefix); break; case dl_unload_fail: @@ -340,12 +337,15 @@ namespace r1 { static std::once_flag init_dl_data_state; static struct ap_data_t { - char _path[PATH_MAX+1]; + char *_path; + std::size_t _capacity; std::size_t _len; } ap_data; static void init_ap_data() { #if _WIN32 + ap_data._capacity = MAX_PATH; + ap_data._path = (char*)calloc(ap_data._capacity, 1); // Get handle of our DLL first. HMODULE handle; BOOL brc = GetModuleHandleEx( @@ -356,17 +356,26 @@ namespace r1 { if ( !brc ) { // Error occurred. int err = GetLastError(); DYNAMIC_LINK_WARNING( dl_sys_fail, "GetModuleHandleEx", err ); + free(ap_data._path); + ap_data._path = NULL; + ap_data._capacity = 0; return; } // Now get path to our DLL. - DWORD drc = GetModuleFileName( handle, ap_data._path, static_cast< DWORD >( PATH_MAX ) ); + DWORD drc = GetModuleFileName( handle, ap_data._path, static_cast< DWORD >( ap_data._capacity ) ); if ( drc == 0 ) { // Error occurred. int err = GetLastError(); DYNAMIC_LINK_WARNING( dl_sys_fail, "GetModuleFileName", err ); + free(ap_data._path); + ap_data._path = NULL; + ap_data._capacity = 0; return; } - if ( drc >= PATH_MAX ) { // Buffer too short. + if ( drc >= ap_data._capacity ) { // Buffer too short. DYNAMIC_LINK_WARNING( dl_buff_too_small ); + free(ap_data._path); + ap_data._path = NULL; + ap_data._capacity = 0; return; } // Find the position of the last backslash. @@ -374,12 +383,18 @@ namespace r1 { if ( !backslash ) { // Backslash not found. __TBB_ASSERT_EX( backslash != nullptr, "Unbelievable."); + free(ap_data._path); + ap_data._path = NULL; + ap_data._capacity = 0; return; } __TBB_ASSERT_EX( backslash >= ap_data._path, "Unbelievable."); ap_data._len = (std::size_t)(backslash - ap_data._path) + 1; *(backslash+1) = 0; #else + // Initial capacity, double until large enough + ap_data._capacity = 4096; + ap_data._path = (char*)calloc(ap_data._capacity, 1); // There is an use case, when we want to find TBB library, not just some shared object // providing "dynamic_link" symbol (it can be shared object that directly includes // dynamic_link.cpp). For this case we use a public TBB symbol. Searching for public symbol @@ -397,6 +412,9 @@ namespace r1 { if ( !res ) { char const * err = dlerror(); DYNAMIC_LINK_WARNING( dl_sys_fail, "dladdr", err ); + free(ap_data._path); + ap_data._path = NULL; + ap_data._capacity = 0; return; } else { __TBB_ASSERT_EX( dlinfo.dli_fname!=nullptr, "Unbelievable." ); @@ -416,9 +434,14 @@ namespace r1 { ap_data._len = 0; } else { // The library path is relative so get the current working directory - if ( !getcwd( ap_data._path, sizeof(ap_data._path)/sizeof(ap_data._path[0]) ) ) { - DYNAMIC_LINK_WARNING( dl_buff_too_small ); - return; + while ( !getcwd( ap_data._path, ap_data._capacity) ) { + free(ap_data._path); + ap_data._capacity *= 2; + ap_data._path = (char*)calloc(ap_data._capacity, 1); + if (NULL == ap_data._path) { + DYNAMIC_LINK_WARNING( dl_buff_too_small ); + return; + } } ap_data._len = std::strlen( ap_data._path ); ap_data._path[ap_data._len++]='/'; @@ -427,9 +450,12 @@ namespace r1 { if ( fname_len>0 ) { ap_data._len += fname_len; - if ( ap_data._len>PATH_MAX ) { + if ( ap_data._len>ap_data._capacity ) { DYNAMIC_LINK_WARNING( dl_buff_too_small ); ap_data._len=0; + free(ap_data._path); + ap_data._path = NULL; + ap_data._capacity = 0; return; } std::strncpy( ap_data._path+rc, dlinfo.dli_fname, fname_len ); @@ -463,7 +489,9 @@ namespace r1 { if ( full_len < len ) { __TBB_ASSERT_EX( ap_data._path[ap_data._len] == 0, nullptr ); __TBB_ASSERT_EX( std::strlen(ap_data._path) == ap_data._len, nullptr ); - std::strncpy( path, ap_data._path, ap_data._len + 1 ); + // No need for strncpy, test above confirmed enough space + // and do not need zero padding at the end. + std::strcpy( path, ap_data._path); __TBB_ASSERT_EX( path[ap_data._len] == 0, nullptr ); std::strncat( path, name, len - ap_data._len ); __TBB_ASSERT_EX( std::strlen(path) == full_len, nullptr ); @@ -662,19 +690,18 @@ namespace r1 { * occurs, in which case the error is optionally reported. */ bool has_valid_signature(const char* filepath, const std::size_t length) { - __TBB_ASSERT_EX(length <= PATH_MAX, "Too small buffer for path conversion"); - wchar_t wfilepath[PATH_MAX] = {0}; + std::unique_ptr wfilepath(new wchar_t[length+1]); { std::mbstate_t state{}; const char* ansi_filepath = filepath; // mbsrtowcs moves original pointer - const size_t num_converted = mbsrtowcs(wfilepath, &ansi_filepath, length, &state); + const size_t num_converted = mbsrtowcs(wfilepath.get(), &ansi_filepath, length, &state); if (num_converted == std::size_t(-1)) return false; } WINTRUST_FILE_INFO fdata; std::memset(&fdata, 0, sizeof(fdata)); fdata.cbStruct = sizeof(WINTRUST_FILE_INFO); - fdata.pcwszFilePath = wfilepath; + fdata.pcwszFilePath = wfilepath.get(); // Check that the certificate used to sign the specified file chains up to a root // certificate located in the trusted root certificate store, implying that the identity of @@ -710,29 +737,26 @@ namespace r1 { dynamic_link_handle library_handle = nullptr; #if __TBB_DYNAMIC_LOAD_ENABLED const char* path = library; - std::size_t const len = PATH_MAX + 1; - char absolute_path[ len ] = {0}; + std::size_t len = abs_path(library, NULL, 1); + std::unique_ptr absolute_path(new char[len]); std::size_t length = 0; const bool build_absolute_path = flags & DYNAMIC_LINK_BUILD_ABSOLUTE_PATH; if (build_absolute_path) { - length = abs_path( library, absolute_path, len ); - if (length > len) { - DYNAMIC_LINK_WARNING( dl_buff_too_small ); - return nullptr; - } else if (length == 0) { + length = abs_path( library, absolute_path.get(), len ); + if (length == 0) { // length == 0 means failing of init_ap_data so the warning has already been issued. return nullptr; - } else if (!file_exists(absolute_path)) { + } else if (!file_exists(absolute_path.get())) { // Path to a file has been built manually. It is not proven to exist however. - DYNAMIC_LINK_WARNING( dl_lib_not_found, absolute_path, dlerror() ); + DYNAMIC_LINK_WARNING( dl_lib_not_found, absolute_path.get(), dlerror() ); return nullptr; } - path = absolute_path; + path = absolute_path.get(); } #if _WIN32 #if !__TBB_SKIP_DEPENDENCY_SIGNATURE_VERIFICATION if (!build_absolute_path) { // Get the path if it is not yet built - length = get_module_path(absolute_path, len, library); + length = get_module_path(absolute_path.get(), (unsigned)len, library); if (length == 0) { DYNAMIC_LINK_WARNING( dl_lib_not_found, path, dlerror() ); return library_handle; @@ -741,7 +765,7 @@ namespace r1 { return library_handle; } length += 1; // Count terminating NULL character as part of string length - path = absolute_path; + path = absolute_path.get(); } if (!has_valid_signature(path, length)) diff --git a/src/tbb/dynamic_link.h b/src/tbb/dynamic_link.h index 635900b7e8..a1861f1edf 100644 --- a/src/tbb/dynamic_link.h +++ b/src/tbb/dynamic_link.h @@ -1,5 +1,6 @@ /* Copyright (c) 2005-2025 Intel Corporation + Copyright (c) 2026 UXL Foundation Contributors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -132,8 +133,7 @@ enum dynamic_link_error_t : int { // System call returned error status dl_sys_fail, // char const * func, dlerr_t err - // Internal intermediate buffer is too small, consider setting PATH_MAX - // macro to a larger value + // Internal intermediate buffer is too small dl_buff_too_small, // none // An error during library unload diff --git a/src/tbb/tools_api/ittnotify_static.c b/src/tbb/tools_api/ittnotify_static.c index f120bdd3ec..22fe227332 100644 --- a/src/tbb/tools_api/ittnotify_static.c +++ b/src/tbb/tools_api/ittnotify_static.c @@ -20,9 +20,6 @@ #include "ittnotify_config.h" #if ITT_PLATFORM==ITT_PLATFORM_WIN -#if !defined(PATH_MAX) -#define PATH_MAX 512 -#endif #else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */ #include #include diff --git a/test/common/utils_concurrency_limit.h b/test/common/utils_concurrency_limit.h index c19b11e6a6..90ffb82e38 100644 --- a/test/common/utils_concurrency_limit.h +++ b/test/common/utils_concurrency_limit.h @@ -207,11 +207,12 @@ class cgroup_info { } static bool try_read_cgroup_v1_num_cpus_from(const char* dir, int& num_cpus) { - char path[PATH_MAX] = {0}; - if (std::snprintf(path, PATH_MAX, "%s/cpu.cfs_quota_us", dir) < 0) + std::size_t pathlen = strlen(dir) + 20; + std::unique_ptr path(new char[pathlen]); + if (std::snprintf(path.get(), pathlen, "%s/cpu.cfs_quota_us", dir) < 0) return false; // Failed to create path - unique_file_t fd(std::fopen(path, "r"), &close_file); + unique_file_t fd(std::fopen(path.get(), "r"), &close_file); if (!fd) return false; @@ -224,10 +225,10 @@ class cgroup_info { return true; } - if (std::snprintf(path, PATH_MAX, "%s/cpu.cfs_period_us", dir) < 0) + if (std::snprintf(path.get(), pathlen, "%s/cpu.cfs_period_us", dir) < 0) return false; // Failed to create path - fd.reset(std::fopen(path, "r")); + fd.reset(std::fopen(path.get(), "r")); if (!fd) return false; @@ -240,11 +241,12 @@ class cgroup_info { } static bool try_read_cgroup_v2_num_cpus_from(const char* dir, int& num_cpus) { - char path[PATH_MAX] = {0}; - if (std::snprintf(path, PATH_MAX, "%s/cpu.max", dir) < 0) + std::size_t pathlen = strlen(dir) + 10; + std::unique_ptr path(new char[pathlen]); + if (std::snprintf(path.get(), pathlen, "%s/cpu.max", dir) < 0) return false; - unique_file_t fd(std::fopen(path, "r"), &close_file); + unique_file_t fd(std::fopen(path.get(), "r"), &close_file); if (!fd) return false; @@ -272,7 +274,8 @@ class cgroup_info { cgroup_paths& paths_cache) { int num_cpus = error_value; // Initialize to an impossible value - char dir[PATH_MAX] = {0}; + std::size_t dirlen = strlen(mnt_dir) + rel_path_size + 2; + std::unique_ptr dir(new char[dirlen]); if (!std::strncmp(mnt_type, "cgroup2", 7)) { // Found cgroup v2 mount entry // At first, try reading CPU quota directly if (try_read_cgroup_v2_num_cpus_from(mnt_dir, num_cpus)) @@ -282,8 +285,8 @@ class cgroup_info { cache_relative_path_for(cgroup_fd, paths_cache); // Now try reading including relative path - if (std::snprintf(dir, PATH_MAX, "%s/%s", mnt_dir, paths_cache.v2_relative_path) >= 0) - try_read_cgroup_v2_num_cpus_from(dir, num_cpus); + if (std::snprintf(dir.get(), dirlen, "%s/%s", mnt_dir, paths_cache.v2_relative_path) >= 0) + try_read_cgroup_v2_num_cpus_from(dir.get(), num_cpus); return num_cpus; } @@ -295,8 +298,8 @@ class cgroup_info { if (!*paths_cache.v1_relative_path) cache_relative_path_for(cgroup_fd, paths_cache); - if (std::snprintf(dir, PATH_MAX, "%s/%s", mnt_dir, paths_cache.v1_relative_path) >= 0) - try_read_cgroup_v1_num_cpus_from(dir, num_cpus); + if (std::snprintf(dir.get(), dirlen, "%s/%s", mnt_dir, paths_cache.v1_relative_path) >= 0) + try_read_cgroup_v1_num_cpus_from(dir.get(), num_cpus); return num_cpus; } diff --git a/test/tbb/test_dynamic_link.cpp b/test/tbb/test_dynamic_link.cpp index f60a4288df..1540ae4de4 100644 --- a/test/tbb/test_dynamic_link.cpp +++ b/test/tbb/test_dynamic_link.cpp @@ -165,17 +165,17 @@ TEST_CASE("Test dynamic_link with existing library") { //! symbols (on Linux) // \brief \ref requirement TEST_CASE("Test dynamic_link with bad library") { - const int size = PATH_MAX + 1; const char* lib_name = TEST_LIBRARY_NAME("stub_unsigned"); - char path[size] = {0}; - const int msg_size = size + 128; // Path to the file + message - char msg[msg_size] = {0}; + const std::size_t size = tbb::detail::r1::abs_path(lib_name, NULL, 1) + 1; + std::unique_ptr path(new char[size]); + const std::size_t msg_size = size + 128; // Path to the file + message + std::unique_ptr msg(new char[msg_size]); #if !__TBB_WIN8UI_SUPPORT - const std::size_t len = tbb::detail::r1::abs_path(lib_name, path, sizeof(path)); - REQUIRE_MESSAGE((0 < len && len <= PATH_MAX), "The path to the library is not built"); - std::snprintf(msg, msg_size, "Test prerequisite is not held - the path \"%s\" must exist", path); - REQUIRE_MESSAGE(tbb::detail::r1::file_exists(path), msg); + const std::size_t len = tbb::detail::r1::abs_path(lib_name, path.get(), size); + REQUIRE_MESSAGE((0 < len && len < size), "The path to the library is not built"); + std::snprintf(msg.get(), msg_size, "Test prerequisite is not held - the path \"%s\" must exist", path.get()); + REQUIRE_MESSAGE(tbb::detail::r1::file_exists(path.get()), msg.get()); #endif // The library exists, check that it will not be loaded. @@ -191,14 +191,14 @@ TEST_CASE("Test dynamic_link with bad library") { const bool link_result = tbb::detail::r1::dynamic_link(lib_name, table, sizeof(table) / sizeof(table[0]), /*handle*/nullptr, load_flags); - std::snprintf(msg, msg_size, "The library \"%s\" was loaded but should not have been.", path); + std::snprintf(msg.get(), msg_size, "The library \"%s\" was loaded but should not have been.", path.get()); // Expectation is that the library will not be loaded because: // a) On Windows the library is unsigned // b) On Linux the library does not have exported symbols const bool expected_link_result = false; - REQUIRE_MESSAGE(expected_link_result == link_result, msg); + REQUIRE_MESSAGE(expected_link_result == link_result, msg.get()); REQUIRE_MESSAGE(nullptr == handler, "The symbol should not be changed."); // TODO: Verify the warning message contains "TBB dynamic link warning: The module // \".*stub_unsigned.*.dll\" is unsigned or has invalid signature."