1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /* [Standardize-exceptions]: Performance-sensitive
16  * [reason]: Strict parameter verification has been done before use
17  */
18 
19 #ifndef __SECURECTYPE_H__A7BBB686_AADA_451B_B9F9_44DACDAE18A7
20 #define __SECURECTYPE_H__A7BBB686_AADA_451B_B9F9_44DACDAE18A7
21 
22 #ifndef SECUREC_ONLY_DECLARE_MEMSET
23 /* Shielding VC symbol redefinition warning */
24 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
25 #ifdef STDC_WANT_SECURE_LIB__
26 #undef STDC_WANT_SECURE_LIB__
27 #endif
28 #define STDC_WANT_SECURE_LIB__ 0
29 #ifdef CRTIMP_ALTERNATIVE
30 #undef CRTIMP_ALTERNATIVE
31 #endif
32 #define CRTIMP_ALTERNATIVE
33 #endif
34 #endif
35 
36 #if SECUREC_IN_KERNEL
37 #include <linux/kernel.h>
38 #include <linux/module.h>
39 #else
40 #include <stdio.h>
41 #include <string.h>
42 #include <stdlib.h>
43 #endif
44 
45 /* if enable SECUREC_COMPATIBLE_WIN_FORMAT, the output format will be compatible to Windows. */
46 #if (defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER))
47 #define SECUREC_COMPATIBLE_WIN_FORMAT
48 #endif
49 
50 #if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
51 /* in windows platform, can't use optimized function for there is no __builtin_constant_p like function */
52 /* If need optimized macro, can define this: define __builtin_constant_p(x) 0 */
53 #ifdef SECUREC_WITH_PERFORMANCE_ADDONS
54 #undef SECUREC_WITH_PERFORMANCE_ADDONS
55 #define SECUREC_WITH_PERFORMANCE_ADDONS 0
56 #endif
57 #endif
58 
59 #if defined(__VXWORKS__) || defined(__vxworks) || defined(__VXWORKS) || defined(_VXWORKS_PLATFORM_)  || \
60     defined(SECUREC_VXWORKS_VERSION_5_4)
61 #if  !defined(SECUREC_VXWORKS_PLATFORM)
62 #define SECUREC_VXWORKS_PLATFORM
63 #endif
64 #endif
65 
66 /* if enable SECUREC_COMPATIBLE_LINUX_FORMAT, the output format will be compatible to Linux. */
67 #if !(defined(SECUREC_COMPATIBLE_WIN_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM))
68 #define SECUREC_COMPATIBLE_LINUX_FORMAT
69 #endif
70 #ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
71 #include <stddef.h>
72 #endif
73 
74 /* add  the -DSECUREC_SUPPORT_FORMAT_WARNING  compiler option to supoort  -Wformat.
75  * default does not check the format is that the same data type in the actual code
76  * in the product is different in the original data type definition of VxWorks and Linux.
77  */
78 #ifndef SECUREC_SUPPORT_FORMAT_WARNING
79 #define SECUREC_SUPPORT_FORMAT_WARNING 0
80 #endif
81 
82 /* SECUREC_PCLINT for tool do not recognize __attribute__  just for pclint */
83 #if SECUREC_SUPPORT_FORMAT_WARNING && !defined(SECUREC_PCLINT)
84 #define SECUREC_ATTRIBUTE(x, y)  __attribute__((format(printf, (x), (y))))
85 #else
86 #define SECUREC_ATTRIBUTE(x, y)
87 #endif
88 
89 /* SECUREC_PCLINT for tool do not recognize __builtin_expect ,just for pclint */
90 #if defined(__GNUC__) && \
91     ((__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3))) && \
92     !defined(SECUREC_PCLINT)
93 /* This is a built-in function that can be used without a declaration, if you encounter an undeclared compilation alarm,
94  * you can add -DSECUREC_NEED_BUILTIN_EXPECT_DECLARE to compiler options
95  */
96 #if defined(SECUREC_NEED_BUILTIN_EXPECT_DECLARE)
97 long __builtin_expect(long exp, long c);
98 #endif
99 #define SECUREC_LIKELY(x) __builtin_expect(!!(x), 1)
100 #define SECUREC_UNLIKELY(x) __builtin_expect(!!(x), 0)
101 #else
102 #define SECUREC_LIKELY(x) (x)
103 #define SECUREC_UNLIKELY(x) (x)
104 #endif
105 
106 /* define the max length of the string */
107 #define SECUREC_STRING_MAX_LEN (0x7fffffffUL)
108 #define SECUREC_WCHAR_STRING_MAX_LEN (SECUREC_STRING_MAX_LEN / sizeof(wchar_t))
109 
110 /* add SECUREC_MEM_MAX_LEN for memcpy and memmove */
111 #define SECUREC_MEM_MAX_LEN (0x7fffffffUL)
112 #define SECUREC_WCHAR_MEM_MAX_LEN (SECUREC_MEM_MAX_LEN / sizeof(wchar_t))
113 
114 #if SECUREC_STRING_MAX_LEN > 0x7fffffff
115 #error "max string is 2G"
116 #endif
117 
118 #if (defined(__GNUC__ ) && defined(__SIZEOF_POINTER__ ))
119 #if (__SIZEOF_POINTER__ != 4) && (__SIZEOF_POINTER__ != 8)
120 #error "unsupported system"
121 #endif
122 #endif
123 
124 #if defined(_WIN64) || defined(WIN64) || defined(__LP64__) || defined(_LP64)
125 #define SECUREC_ON_64BITS
126 #endif
127 
128 #if (!defined(SECUREC_ON_64BITS) && defined(__GNUC__ ) && defined(__SIZEOF_POINTER__ ))
129 #if __SIZEOF_POINTER__ == 8
130 #define SECUREC_ON_64BITS
131 #endif
132 #endif
133 
134 #if defined(__SVR4) || defined(__svr4__)
135 #define SECUREC_ON_SOLARIS
136 #endif
137 
138 #if (defined(__hpux) || defined(_AIX) || defined(SECUREC_ON_SOLARIS))
139 #define SECUREC_ON_UNIX
140 #endif
141 
142 /* codes should run under the macro SECUREC_COMPATIBLE_LINUX_FORMAT in unknown system on default,
143  * and strtold. The function
144  * strtold is referenced first at ISO9899:1999(C99), and some old compilers can
145  * not support these functions. Here provides a macro to open these functions:
146  * SECUREC_SUPPORT_STRTOLD  -- if defined, strtold will   be used
147  */
148 #ifndef SECUREC_SUPPORT_STRTOLD
149 #define SECUREC_SUPPORT_STRTOLD 0
150 #if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT))
151 #if defined(__USE_ISOC99)  || \
152     (defined(_AIX) && defined(_ISOC99_SOURCE)) || \
153     (defined(__hpux) && defined(__ia64)) || \
154     (defined(SECUREC_ON_SOLARIS) &&  (!defined(_STRICT_STDC) && !defined(__XOPEN_OR_POSIX)) || \
155      defined(_STDC_C99) || defined(__EXTENSIONS__))
156 #undef  SECUREC_SUPPORT_STRTOLD
157 #define SECUREC_SUPPORT_STRTOLD 1
158 #endif
159 #endif
160 #if ((defined(SECUREC_WRLINUX_BELOW4) || defined(_WRLINUX_BELOW4_)))
161 #undef  SECUREC_SUPPORT_STRTOLD
162 #define SECUREC_SUPPORT_STRTOLD 0
163 #endif
164 #endif
165 
166 #if SECUREC_WITH_PERFORMANCE_ADDONS
167 
168 #ifndef SECUREC_TWO_MIN
169 #define SECUREC_TWO_MIN(a, b) ((a) < (b) ? (a) : (b))
170 #endif
171 
172 /* for strncpy_s performance optimization */
173 #define SECUREC_STRNCPY_SM(dest, destMax, src, count) \
174     (((void *)dest != NULL && (void *)src != NULL  && (size_t)destMax >0 && \
175         (((unsigned long long)(destMax) & (unsigned long long)(-2)) < SECUREC_STRING_MAX_LEN) && \
176         (SECUREC_TWO_MIN(count, strlen(src)) + 1) <= (size_t)destMax ) ? \
177         ((count < strlen(src))? (memcpy(dest, src, count), *((char *)dest + count) = '\0', EOK): \
178         (memcpy(dest, src, strlen(src) + 1), EOK)) : (strncpy_error(dest, destMax, src, count)))
179 
180 #define SECUREC_STRCPY_SM(dest, destMax, src) \
181     (((void *)dest != NULL && (void *)src != NULL && (size_t)destMax >0 && \
182         (((unsigned long long)(destMax) & (unsigned long long)(-2)) < SECUREC_STRING_MAX_LEN) && \
183         (strlen(src) + 1) <= (size_t)destMax) ? (memcpy(dest, src, strlen(src) + 1), EOK): \
184         (strcpy_error(dest, destMax, src)))
185 
186 /* for strcat_s performance optimization */
187 #if defined(__GNUC__)
188 #define SECUREC_STRCAT_SM(dest, destMax, src) \
189     ( { \
190         int catRet = EOK; \
191         if ((void *)dest != NULL && (void *)src != NULL && (size_t)(destMax) >0 && \
192             (((unsigned long long)(destMax) & (unsigned long long)(-2)) < SECUREC_STRING_MAX_LEN)) { \
193             char *catTmpDst = (dest); \
194             size_t catRestSize = (destMax); \
195             while (catRestSize > 0 && *catTmpDst) { \
196                 ++catTmpDst; \
197                 --catRestSize; \
198             } \
199             if (catRestSize == 0) { \
200                 catRet = EINVAL; \
201             } else if ((strlen(src) + 1) <= catRestSize) { \
202                 memcpy(catTmpDst, (src), strlen(src) + 1); \
203                 catRet = EOK; \
204             } else { \
205                 catRet = ERANGE; \
206             } \
207             if (catRet != EOK) { \
208                 catRet = strcat_s((dest), (destMax), (src)); \
209             } \
210         } else { \
211             catRet = strcat_s((dest), (destMax), (src)); \
212         } \
213         catRet; \
214     })
215 #else
216 #define SECUREC_STRCAT_SM(dest, destMax, src) strcat_s(dest, destMax, src)
217 #endif
218 
219 /* for strncat_s performance optimization */
220 #if defined(__GNUC__)
221 #define SECUREC_STRNCAT_SM(dest, destMax, src, count) \
222     ({ \
223         int ncatRet = EOK; \
224         if ((void *)dest != NULL && (void *)src != NULL && (size_t)destMax > 0 && \
225             (((unsigned long long)(destMax) & (unsigned long long)(-2)) < SECUREC_STRING_MAX_LEN)  && \
226             (((unsigned long long)(count) & (unsigned long long)(-2)) < SECUREC_STRING_MAX_LEN)) { \
227             char *ncatTmpDest = (dest); \
228             size_t ncatRestSize = (destMax); \
229             while (ncatRestSize > 0 && *ncatTmpDest) { \
230                 ++ncatTmpDest; \
231                 --ncatRestSize; \
232             } \
233             if (ncatRestSize == 0) { \
234                 ncatRet = EINVAL; \
235             } else if ((SECUREC_TWO_MIN((count), strlen(src)) + 1) <= ncatRestSize ) { \
236                 if ((count) < strlen(src)) { \
237                     memcpy(ncatTmpDest, (src), (count)); \
238                     *(ncatTmpDest + (count)) = '\0'; \
239                 } else { \
240                     memcpy(ncatTmpDest, (src), strlen(src) + 1); \
241                 } \
242             } else { \
243                 ncatRet = ERANGE; \
244             } \
245             if (ncatRet != EOK) { \
246                 ncatRet = strncat_s((dest), (destMax), (src), (count)); \
247             } \
248         } else { \
249             ncatRet = strncat_s((dest), (destMax), (src), (count)); \
250         } \
251         ncatRet; \
252     })
253 #else
254 #define SECUREC_STRNCAT_SM(dest, destMax, src, count) strncat_s(dest, destMax, src, count)
255 #endif
256 
257 /* SECUREC_MEMCPY_SM do NOT check buffer overlap by default */
258 #define  SECUREC_MEMCPY_SM(dest, destMax, src, count) \
259     (!(((size_t)destMax == 0 ) || (((unsigned long long)(destMax) & \
260       (unsigned long long)(-2)) > SECUREC_MEM_MAX_LEN) || \
261         ((size_t)count > (size_t)destMax) || ((void *)dest) == NULL || ((void *)src == NULL))? \
262         (memcpy(dest, src, count), EOK) : \
263         (memcpy_s(dest, destMax, src, count)))
264 
265 #define  SECUREC_MEMSET_SM(dest, destMax, c, count) \
266     (!(((size_t)destMax == 0 ) || (((unsigned long long)(destMax) & \
267        (unsigned long long)(-2)) > SECUREC_MEM_MAX_LEN) || \
268         ((void *)dest == NULL) || ((size_t)count > (size_t)destMax)) ? \
269         (memset(dest, c, count), EOK) : \
270         (memset_s(dest, destMax, c, count)))
271 
272 #endif
273 #endif /* __SECURECTYPE_H__A7BBB686_AADA_451B_B9F9_44DACDAE18A7 */
274