• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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