1 /*
2 * Copyright (c) 2021 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] Use unsafe function: Portability
16 * [reason] Use unsafe function to implement security function to maintain platform compatibility.
17 * And sufficient input validation is performed before calling
18 */
19
20 #include "securecutil.h"
21
22 #ifndef SECUREC_MEMSET_WITH_PERFORMANCE
23 #define SECUREC_MEMSET_WITH_PERFORMANCE 0
24 #endif
25
26 #if SECUREC_WITH_PERFORMANCE_ADDONS || SECUREC_MEMSET_WITH_PERFORMANCE
27
28 /* use union to clear strict-aliasing warning */
29 typedef union {
30 SecStrBuf32 buf32;
31 SecStrBuf31 buf31;
32 SecStrBuf30 buf30;
33 SecStrBuf29 buf29;
34 SecStrBuf28 buf28;
35 SecStrBuf27 buf27;
36 SecStrBuf26 buf26;
37 SecStrBuf25 buf25;
38 SecStrBuf24 buf24;
39 SecStrBuf23 buf23;
40 SecStrBuf22 buf22;
41 SecStrBuf21 buf21;
42 SecStrBuf20 buf20;
43 SecStrBuf19 buf19;
44 SecStrBuf18 buf18;
45 SecStrBuf17 buf17;
46 SecStrBuf16 buf16;
47 SecStrBuf15 buf15;
48 SecStrBuf14 buf14;
49 SecStrBuf13 buf13;
50 SecStrBuf12 buf12;
51 SecStrBuf11 buf11;
52 SecStrBuf10 buf10;
53 SecStrBuf9 buf9;
54 SecStrBuf8 buf8;
55 SecStrBuf7 buf7;
56 SecStrBuf6 buf6;
57 SecStrBuf5 buf5;
58 SecStrBuf4 buf4;
59 SecStrBuf3 buf3;
60 SecStrBuf2 buf2;
61 SecStrBuf1 buf1;
62 } SecStrBuf32Union;
63 /* C standard initializes the first member of the consortium. */
64 static const SecStrBuf32 g_allZero = {{'\0','\0','\0','\0','\0','\0','\0','\0',
65 '\0','\0','\0','\0','\0','\0','\0','\0',
66 '\0','\0','\0','\0','\0','\0','\0','\0',
67 '\0','\0','\0','\0','\0','\0','\0','\0'}};
68 static const SecStrBuf32 g_allFF = {{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
69 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
70 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
71 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}};
72
SecStrictAliasingCast(const SecStrBuf32 * buf)73 static const SecStrBuf32Union *SecStrictAliasingCast(const SecStrBuf32 *buf)
74 {
75 return (const SecStrBuf32Union *)buf;
76 }
77
78 #ifndef SECUREC_MEMSET_THRESHOLD_SIZE
79 #define SECUREC_MEMSET_THRESHOLD_SIZE (32UL)
80 #endif
81
82 #define SECUREC_COPY_STRUCT_4_ZERO(num) \
83 case num: \
84 *(SecStrBuf##num *)dest = *(const SecStrBuf##num *)(&((SecStrictAliasingCast(&g_allZero))->buf##num)); \
85 break;
86
87 #define SECUREC_COPY_STRUCT_4_FF(num) \
88 case num: \
89 *(SecStrBuf##num *)dest = *(const SecStrBuf##num *)(&((SecStrictAliasingCast(&g_allFF))->buf##num)); \
90 break;
91
92 #define SECUREC_UNALIGNED_SET do { \
93 char *pcDest = (char *)dest; \
94 switch (count) { \
95 case 32: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
96 case 31: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
97 case 30: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
98 case 29: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
99 case 28: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
100 case 27: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
101 case 26: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
102 case 25: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
103 case 24: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
104 case 23: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
105 case 22: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
106 case 21: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
107 case 20: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
108 case 19: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
109 case 18: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
110 case 17: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
111 case 16: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
112 case 15: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
113 case 14: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
114 case 13: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
115 case 12: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
116 case 11: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
117 case 10: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
118 case 9: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
119 case 8: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
120 case 7: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
121 case 6: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
122 case 5: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
123 case 4: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
124 case 3: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
125 case 2: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
126 case 1: *pcDest++ = (char)c; /* fall-through */ /* FALLTHRU */ \
127 default:break; \
128 } \
129 } SECUREC_WHILE_ZERO
130
131 #define SECUREC_ALIGNED_SET_OPT_ZERO_FF do { \
132 switch (c) { \
133 case 0: \
134 switch (count) { \
135 SECUREC_COPY_STRUCT_4_ZERO(1) \
136 SECUREC_COPY_STRUCT_4_ZERO(2) \
137 SECUREC_COPY_STRUCT_4_ZERO(3) \
138 SECUREC_COPY_STRUCT_4_ZERO(4) \
139 SECUREC_COPY_STRUCT_4_ZERO(5) \
140 SECUREC_COPY_STRUCT_4_ZERO(6) \
141 SECUREC_COPY_STRUCT_4_ZERO(7) \
142 SECUREC_COPY_STRUCT_4_ZERO(8) \
143 SECUREC_COPY_STRUCT_4_ZERO(9) \
144 SECUREC_COPY_STRUCT_4_ZERO(10) \
145 SECUREC_COPY_STRUCT_4_ZERO(11) \
146 SECUREC_COPY_STRUCT_4_ZERO(12) \
147 SECUREC_COPY_STRUCT_4_ZERO(13) \
148 SECUREC_COPY_STRUCT_4_ZERO(14) \
149 SECUREC_COPY_STRUCT_4_ZERO(15) \
150 SECUREC_COPY_STRUCT_4_ZERO(16) \
151 SECUREC_COPY_STRUCT_4_ZERO(17) \
152 SECUREC_COPY_STRUCT_4_ZERO(18) \
153 SECUREC_COPY_STRUCT_4_ZERO(19) \
154 SECUREC_COPY_STRUCT_4_ZERO(20) \
155 SECUREC_COPY_STRUCT_4_ZERO(21) \
156 SECUREC_COPY_STRUCT_4_ZERO(22) \
157 SECUREC_COPY_STRUCT_4_ZERO(23) \
158 SECUREC_COPY_STRUCT_4_ZERO(24) \
159 SECUREC_COPY_STRUCT_4_ZERO(25) \
160 SECUREC_COPY_STRUCT_4_ZERO(26) \
161 SECUREC_COPY_STRUCT_4_ZERO(27) \
162 SECUREC_COPY_STRUCT_4_ZERO(28) \
163 SECUREC_COPY_STRUCT_4_ZERO(29) \
164 SECUREC_COPY_STRUCT_4_ZERO(30) \
165 SECUREC_COPY_STRUCT_4_ZERO(31) \
166 SECUREC_COPY_STRUCT_4_ZERO(32) \
167 default:break; \
168 } \
169 break; \
170 case 0xFF: \
171 switch (count) { \
172 SECUREC_COPY_STRUCT_4_FF(1) \
173 SECUREC_COPY_STRUCT_4_FF(2) \
174 SECUREC_COPY_STRUCT_4_FF(3) \
175 SECUREC_COPY_STRUCT_4_FF(4) \
176 SECUREC_COPY_STRUCT_4_FF(5) \
177 SECUREC_COPY_STRUCT_4_FF(6) \
178 SECUREC_COPY_STRUCT_4_FF(7) \
179 SECUREC_COPY_STRUCT_4_FF(8) \
180 SECUREC_COPY_STRUCT_4_FF(9) \
181 SECUREC_COPY_STRUCT_4_FF(10) \
182 SECUREC_COPY_STRUCT_4_FF(11) \
183 SECUREC_COPY_STRUCT_4_FF(12) \
184 SECUREC_COPY_STRUCT_4_FF(13) \
185 SECUREC_COPY_STRUCT_4_FF(14) \
186 SECUREC_COPY_STRUCT_4_FF(15) \
187 SECUREC_COPY_STRUCT_4_FF(16) \
188 SECUREC_COPY_STRUCT_4_FF(17) \
189 SECUREC_COPY_STRUCT_4_FF(18) \
190 SECUREC_COPY_STRUCT_4_FF(19) \
191 SECUREC_COPY_STRUCT_4_FF(20) \
192 SECUREC_COPY_STRUCT_4_FF(21) \
193 SECUREC_COPY_STRUCT_4_FF(22) \
194 SECUREC_COPY_STRUCT_4_FF(23) \
195 SECUREC_COPY_STRUCT_4_FF(24) \
196 SECUREC_COPY_STRUCT_4_FF(25) \
197 SECUREC_COPY_STRUCT_4_FF(26) \
198 SECUREC_COPY_STRUCT_4_FF(27) \
199 SECUREC_COPY_STRUCT_4_FF(28) \
200 SECUREC_COPY_STRUCT_4_FF(29) \
201 SECUREC_COPY_STRUCT_4_FF(30) \
202 SECUREC_COPY_STRUCT_4_FF(31) \
203 SECUREC_COPY_STRUCT_4_FF(32) \
204 default:break; \
205 } \
206 break; \
207 default: \
208 SECUREC_UNALIGNED_SET; \
209 } /* END switch */ \
210 } SECUREC_WHILE_ZERO
211 #endif
212
SecMemsetError(void * dest,size_t destMax,int c,size_t count)213 static errno_t SecMemsetError(void *dest, size_t destMax, int c, size_t count)
214 {
215 if (destMax == 0 || destMax > SECUREC_MEM_MAX_LEN) {
216 SECUREC_ERROR_INVALID_RANGE("memset_s");
217 return ERANGE;
218 }
219 if (dest == NULL) {
220 SECUREC_ERROR_INVALID_PARAMTER("memset_s");
221 return EINVAL;
222 }
223 if (count > destMax) {
224 (void)memset(dest, c, destMax); /* set entire buffer to value c */
225 SECUREC_ERROR_INVALID_RANGE("memset_s");
226 return ERANGE_AND_RESET;
227 }
228 return EOK;
229 }
230
231 #if SECUREC_WITH_PERFORMANCE_ADDONS || SECUREC_MEMSET_WITH_PERFORMANCE
SecDoMemsetOpt(void * dest,int c,size_t count)232 static void SecDoMemsetOpt(void *dest, int c, size_t count)
233 {
234 if (count > SECUREC_MEMSET_THRESHOLD_SIZE) {
235 #ifdef SECUREC_USE_ASM
236 (void)memset_opt(dest, c, count);
237 #else
238 (void)memset(dest, c, count);
239 #endif
240 } else {
241 if (SECUREC_ADDR_ALIGNED_8(dest)) {
242 /* use struct assignment */
243 SECUREC_ALIGNED_SET_OPT_ZERO_FF;
244 } else {
245 SECUREC_UNALIGNED_SET;
246 }
247 }
248 return;
249 }
250 #endif
251
252 /*******************************************************************************
253 * <FUNCTION DESCRIPTION>
254 * The memset_s function copies the value of c (converted to an unsigned char)
255 * into each of the first count characters of the object pointed to by dest.
256 *
257 * <INPUT PARAMETERS>
258 * dest Pointer to destination.
259 * destMax The size of the buffer.
260 * c Character to set.
261 * count Number of characters.
262 *
263 * <OUTPUT PARAMETERS>
264 * dest buffer is updated.
265 *
266 * <RETURN VALUE>
267 * EOK Success
268 * EINVAL dest == NULL and destMax != 0 and destMax <= SECUREC_MEM_MAX_LEN
269 * ERANGE destMax is 0 or destMax > SECUREC_MEM_MAX_LEN
270 * ERANGE_AND_RESET count > destMax and destMax != 0 and destMax <= SECUREC_MEM_MAX_LEN and dest != NULL
271 *
272 * if return ERANGE_AND_RESET then fill dest to c ,fill length is destMax
273 *******************************************************************************
274 */
memset_s(void * dest,size_t destMax,int c,size_t count)275 errno_t memset_s(void *dest, size_t destMax, int c, size_t count)
276 {
277 if (SECUREC_LIKELY(count <= destMax && dest != NULL && destMax <= SECUREC_MEM_MAX_LEN)) {
278 #if SECUREC_MEMSET_WITH_PERFORMANCE
279 SecDoMemsetOpt(dest, c, count);
280 #else
281 #ifdef SECUREC_USE_ASM
282 (void)memset_opt(dest, c, count);
283 #else
284 (void)memset(dest, c, count);
285 #endif
286 #endif
287 return EOK;
288 } else {
289 /* meet some runtime violation, return error code */
290 return SecMemsetError(dest, destMax, c, count);
291 }
292 }
293
294 #if SECUREC_IN_KERNEL
295 EXPORT_SYMBOL(memset_s);
296 #endif
297
298 #if SECUREC_WITH_PERFORMANCE_ADDONS
299
memset_sOptAsm(void * dest,size_t destMax,int c,size_t count)300 errno_t memset_sOptAsm(void *dest, size_t destMax, int c, size_t count)
301 {
302 if (SECUREC_LIKELY(count <= destMax && dest != NULL && destMax <= SECUREC_MEM_MAX_LEN)) {
303 SecDoMemsetOpt(dest, c, count);
304 return EOK;
305 }
306
307 /* meet some runtime violation, return error code */
308 return SecMemsetError(dest, destMax, c, count);
309 }
310
memset_sOptTc(void * dest,size_t destMax,int c,size_t count)311 errno_t memset_sOptTc(void *dest, size_t destMax, int c, size_t count)
312 {
313 if (SECUREC_LIKELY(count <= destMax && dest != NULL)) {
314 SecDoMemsetOpt(dest, c, count);
315 return EOK;
316 }
317 /* meet some runtime violation, return error code */
318 return SecMemsetError(dest, destMax, c, count);
319
320 }
321 #endif
322
323