| 1 | |
| 2 | //===----------------------------------------------------------------------===// |
| 3 | // |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 5 | // See https://llvm.org/LICENSE.txt for license information. |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | |
| 10 | #ifndef KMP_SAFE_C_API_H |
| 11 | #define KMP_SAFE_C_API_H |
| 12 | |
| 13 | #include <type_traits> |
| 14 | #include "kmp_platform.h" |
| 15 | #include <string.h> |
| 16 | |
| 17 | // Replacement for banned C API |
| 18 | |
| 19 | // Not every unsafe call listed here is handled now, but keeping everything |
| 20 | // in one place should be handy for future maintenance. |
| 21 | #if KMP_OS_WINDOWS && KMP_MSVC_COMPAT |
| 22 | |
| 23 | #define RSIZE_MAX_STR (4UL << 10) // 4KB |
| 24 | |
| 25 | // _malloca was suggested, but it is not a drop-in replacement for _alloca |
| 26 | #define KMP_ALLOCA _alloca |
| 27 | |
| 28 | #define KMP_MEMCPY_S memcpy_s |
| 29 | #define KMP_SNPRINTF sprintf_s |
| 30 | #define KMP_SSCANF sscanf_s |
| 31 | #define KMP_STRCPY_S strcpy_s |
| 32 | #define KMP_STRNCPY_S strncpy_s |
| 33 | #define KMP_STRNCAT_S strncat_s |
| 34 | |
| 35 | // Use this only when buffer size is unknown |
| 36 | #define KMP_MEMCPY(dst, src, cnt) memcpy_s(dst, cnt, src, cnt) |
| 37 | |
| 38 | template <typename T, bool B = std::is_array<T>::value> |
| 39 | struct kmp_get_rmax_t {}; |
| 40 | template <typename T> struct kmp_get_rmax_t<T, false> { |
| 41 | static const size_t value = RSIZE_MAX_STR; |
| 42 | }; |
| 43 | template <typename T> struct kmp_get_rmax_t<T, true> { |
| 44 | static const size_t value = sizeof(T); |
| 45 | }; |
| 46 | #define KMP_STRLEN(str) strnlen_s(str, kmp_get_rmax_t<decltype(str)>::value) |
| 47 | |
| 48 | // Use this only when buffer size is unknown |
| 49 | #define KMP_STRNCPY(dst, src, cnt) strncpy_s(dst, cnt, src, cnt) |
| 50 | |
| 51 | // _TRUNCATE insures buffer size > max string to print. |
| 52 | #define KMP_VSNPRINTF(dst, cnt, fmt, arg) \ |
| 53 | vsnprintf_s(dst, cnt, _TRUNCATE, fmt, arg) |
| 54 | |
| 55 | #else // KMP_OS_WINDOWS |
| 56 | |
| 57 | // For now, these macros use the existing API. |
| 58 | |
| 59 | #if KMP_OS_NETBSD |
| 60 | #define KMP_ALLOCA __builtin_alloca |
| 61 | #else |
| 62 | #define KMP_ALLOCA alloca |
| 63 | #endif |
| 64 | #define KMP_MEMCPY_S(dst, bsz, src, cnt) memcpy(dst, src, cnt) |
| 65 | #define KMP_SNPRINTF snprintf |
| 66 | #define KMP_SSCANF sscanf |
| 67 | #define KMP_STRCPY_S(dst, bsz, src) strcpy(dst, src) |
| 68 | #define KMP_STRNCPY_S(dst, bsz, src, cnt) strncpy(dst, src, cnt) |
| 69 | #define KMP_STRNCAT_S(dst, bsz, src, cnt) strncat(dst, src, cnt) |
| 70 | #define KMP_VSNPRINTF vsnprintf |
| 71 | #define KMP_STRNCPY strncpy |
| 72 | #define KMP_STRLEN strlen |
| 73 | #define KMP_MEMCPY memcpy |
| 74 | |
| 75 | #endif // KMP_OS_WINDOWS |
| 76 | |
| 77 | // Offer truncated version of strncpy |
| 78 | static inline void __kmp_strncpy_truncate(char *buffer, size_t buf_size, |
| 79 | char const *src, size_t src_size) { |
| 80 | if (src_size >= buf_size) { |
| 81 | src_size = buf_size - 1; |
| 82 | } |
| 83 | KMP_STRNCPY_S(buffer, buf_size, src, src_size); |
| 84 | buffer[src_size] = '\0'; |
| 85 | } |
| 86 | |
| 87 | #endif // KMP_SAFE_C_API_H |
| 88 | |