Line data Source code
1 : /*
2 : * Copyright (c) 2018 Cisco and/or its affiliates.
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 : #include <vlib/vlib.h>
16 : #include <vppinfra/string.h>
17 :
18 : static int
19 1 : test_memset_s (vlib_main_t * vm, unformat_input_t * input)
20 : {
21 : u8 dst[64];
22 : int i;
23 : errno_t err;
24 :
25 1 : vlib_cli_output (vm, "Test memset_s...");
26 :
27 1 : err = memset_s (dst, ARRAY_LEN (dst), 0xfe, ARRAY_LEN (dst));
28 :
29 1 : if (err != EOK)
30 0 : return -1;
31 :
32 65 : for (i = 0; i < ARRAY_LEN (dst); i++)
33 64 : if (dst[i] != 0xFE)
34 0 : return -1;
35 :
36 1 : err = memset_s (dst, ARRAY_LEN (dst), 0xfa, ARRAY_LEN (dst) + 1);
37 :
38 1 : if (err == EOK)
39 0 : return -1;
40 :
41 1 : return 0;
42 : }
43 :
44 : static int
45 1 : test_clib_memset (vlib_main_t * vm, unformat_input_t * input)
46 : {
47 : u8 dst[64];
48 : int i;
49 : errno_t err;
50 :
51 1 : vlib_cli_output (vm, "Test clib_memset...");
52 :
53 1 : err = clib_memset (dst, 0xfe, ARRAY_LEN (dst));
54 :
55 1 : if (err != EOK)
56 0 : return -1;
57 :
58 65 : for (i = 0; i < ARRAY_LEN (dst); i++)
59 64 : if (dst[i] != 0xFE)
60 0 : return -1;
61 :
62 1 : return 0;
63 : }
64 :
65 : static int
66 2 : test_memcpy_s (vlib_main_t * vm, unformat_input_t * input)
67 : {
68 : char src[64], dst[64];
69 : int i;
70 : errno_t err;
71 :
72 2 : vlib_cli_output (vm, "Test memcpy_s...");
73 :
74 130 : for (i = 0; i < ARRAY_LEN (src); i++)
75 128 : src[i] = i + 1;
76 :
77 : /* Typical case */
78 2 : err = memcpy_s (dst, sizeof (dst), src, sizeof (src));
79 :
80 2 : if (err != EOK)
81 0 : return -1;
82 :
83 : /* This better not fail but check anyhow */
84 130 : for (i = 0; i < ARRAY_LEN (dst); i++)
85 128 : if (src[i] != dst[i])
86 0 : return -1;
87 :
88 : /*
89 : * Size test: sizeof (src) > sizeof (dst)
90 : * Skip this test when __builtin_constant_p (sizeof (src)) is true.
91 : * This is because memcpy_s_inline skips all the errors checking when the
92 : * the above buildin function returns true which may cause overrun problem
93 : * for dst buffer if this test is executed.
94 : */
95 : if (__builtin_constant_p (sizeof (src)) == 0)
96 : {
97 : err = memcpy_s (dst + 1, sizeof (dst) - 1, src, sizeof (src));
98 :
99 : if (err == EOK)
100 : return -1;
101 : }
102 :
103 : /* overlap fail */
104 2 : err = memcpy_s (dst, sizeof (dst), dst + 1, sizeof (dst) - 1);
105 :
106 2 : if (err == EOK)
107 0 : return -1;
108 :
109 : /* Zero length copy */
110 2 : err = memcpy_s (0, sizeof (dst), src, 0);
111 :
112 2 : if (err != EOK)
113 0 : return -1;
114 :
115 : /* OK, seems to work */
116 2 : return 0;
117 : }
118 :
119 : static int
120 1 : test_clib_memcpy (vlib_main_t * vm, unformat_input_t * input)
121 : {
122 : char src[64], dst[64];
123 : int i;
124 : errno_t err;
125 :
126 1 : vlib_cli_output (vm, "Test clib_memcpy...");
127 :
128 65 : for (i = 0; i < ARRAY_LEN (src); i++)
129 64 : src[i] = i + 1;
130 :
131 : /* Typical case */
132 1 : err = clib_memcpy (dst, src, sizeof (src));
133 :
134 1 : if (err != EOK)
135 0 : return -1;
136 :
137 : /* This better not fail but check anyhow */
138 65 : for (i = 0; i < ARRAY_LEN (dst); i++)
139 64 : if (src[i] != dst[i])
140 0 : return -1;
141 : /* verify it against memcpy */
142 1 : memcpy (dst, src, sizeof (src));
143 :
144 : /* This better not fail but check anyhow */
145 65 : for (i = 0; i < ARRAY_LEN (dst); i++)
146 64 : if (src[i] != dst[i])
147 0 : return -1;
148 :
149 : /* Zero length copy */
150 1 : err = clib_memcpy (0, src, 0);
151 :
152 1 : if (err != EOK)
153 0 : return -1;
154 :
155 : /* OK, seems to work */
156 1 : return 0;
157 : }
158 :
159 : static int
160 1 : test_memcmp_s (vlib_main_t * vm, unformat_input_t * input)
161 : {
162 : char src[64], dst[64];
163 : errno_t err;
164 1 : int diff = 0;
165 :
166 1 : vlib_cli_output (vm, "Test memcmp_s...");
167 :
168 : /* Fill array with different values */
169 1 : err = clib_memset (src, 0x1, ARRAY_LEN (src));
170 1 : if (err != EOK)
171 0 : return -1;
172 1 : err = clib_memset (dst, 0x3, ARRAY_LEN (dst));
173 1 : if (err != EOK)
174 0 : return -1;
175 :
176 : /* s1 > s2, > 0 is expected in diff */
177 1 : err = memcmp_s (dst, ARRAY_LEN (dst), src, ARRAY_LEN (src), &diff);
178 1 : if (err != EOK)
179 0 : return -1;
180 1 : if (!(diff > 0))
181 0 : return -1;
182 :
183 : /* s1 < s2, < 0 is expected in diff */
184 1 : err = memcmp_s (src, ARRAY_LEN (src), dst, ARRAY_LEN (dst), &diff);
185 1 : if (err != EOK)
186 0 : return -1;
187 1 : if (!(diff < 0))
188 0 : return -1;
189 :
190 1 : err = clib_memset (dst, 0x1, ARRAY_LEN (dst));
191 1 : if (err != EOK)
192 0 : return -1;
193 :
194 : /* s1 == s2, 0 is expected in diff */
195 1 : err = memcmp_s (src, ARRAY_LEN (src), dst, ARRAY_LEN (dst), &diff);
196 1 : if (err != EOK)
197 0 : return -1;
198 1 : if (diff != 0)
199 0 : return -1;
200 :
201 : /* Try negative tests */
202 1 : err = memcmp_s (0, 0, 0, 0, 0);
203 1 : if (err != EINVAL)
204 0 : return -1;
205 :
206 : /* Try s2max > s1max */
207 1 : err = memcmp_s (src, ARRAY_LEN (src) - 1, dst, ARRAY_LEN (dst), &diff);
208 1 : if (err != EINVAL)
209 0 : return -1;
210 :
211 : /* OK, seems to work */
212 1 : return 0;
213 : }
214 :
215 : static int
216 1 : test_clib_memcmp (vlib_main_t * vm, unformat_input_t * input)
217 : {
218 : char src[64], dst[64];
219 : errno_t err;
220 : char *s;
221 :
222 1 : vlib_cli_output (vm, "Test clib_memcmp...");
223 :
224 : /* Fill array with different values */
225 1 : err = clib_memset (src, 0x1, ARRAY_LEN (src));
226 1 : if (err != EOK)
227 0 : return -1;
228 1 : err = clib_memset (dst, 0x3, ARRAY_LEN (dst));
229 1 : if (err != EOK)
230 0 : return -1;
231 :
232 : /* s1 > s2, > 0 is expected in diff */
233 1 : if (!(clib_memcmp (dst, src, ARRAY_LEN (src)) > 0))
234 0 : return -1;
235 : /* verify it against memcmp */
236 1 : if (!(memcmp (dst, src, ARRAY_LEN (src)) > 0))
237 0 : return -1;
238 :
239 : /* s1 < s2, < 0 is expected in diff */
240 1 : if (!(clib_memcmp (src, dst, ARRAY_LEN (dst)) < 0))
241 0 : return -1;
242 : /* verify it against memcmp */
243 1 : if (!(memcmp (src, dst, ARRAY_LEN (dst)) < 0))
244 0 : return -1;
245 :
246 1 : err = clib_memset (dst, 0x1, ARRAY_LEN (dst));
247 1 : if (err != EOK)
248 0 : return -1;
249 :
250 : /* s1 == s2, 0 is expected in diff */
251 1 : if (clib_memcmp (src, dst, ARRAY_LEN (dst)) != 0)
252 0 : return -1;
253 : /* verify it against memcmp */
254 1 : if (memcmp (src, dst, ARRAY_LEN (dst)) != 0)
255 0 : return -1;
256 :
257 : /* Try negative tests */
258 1 : s = 0;
259 1 : if (clib_memcmp (s, s, 0) != 0)
260 0 : return -1;
261 : /* verify it against memcmp */
262 : if (memcmp (s, s, 0) != 0)
263 : return -1;
264 :
265 : /* OK, seems to work */
266 1 : return 0;
267 : }
268 :
269 : static int
270 1 : test_strcmp_s (vlib_main_t * vm, unformat_input_t * input)
271 : {
272 1 : char s1[] = "Simplicity is the ultimate sophistication";
273 1 : uword s1len = sizeof (s1) - 1; // excluding null
274 : errno_t err;
275 1 : int indicator = 0;
276 :
277 1 : vlib_cli_output (vm, "Test strcmp_s...");
278 :
279 : /* s1 == s2, 0 is expected */
280 1 : err = strcmp_s (s1, s1len, "Simplicity is the ultimate sophistication",
281 : &indicator);
282 1 : if (err != EOK)
283 0 : return -1;
284 1 : if (indicator != 0)
285 0 : return -1;
286 :
287 : /* s1 > s2, > 0 is expected */
288 1 : err = strcmp_s (s1, s1len, "Simplicity is the ultimate", &indicator);
289 1 : if (err != EOK)
290 0 : return -1;
291 1 : if (!(indicator > 0))
292 0 : return -1;
293 :
294 : /* s1 < s2, < 0 is expected */
295 1 : err = strcmp_s (s1, s1len, "Simplicity is the ultimate sophistication!",
296 : &indicator);
297 1 : if (err != EOK)
298 0 : return -1;
299 1 : if (!(indicator < 0))
300 0 : return -1;
301 :
302 : /* Try some negative tests */
303 :
304 : /* Null pointers test */
305 1 : err = strcmp_s (0, 0, 0, 0);
306 1 : if (err != EINVAL)
307 0 : return -1;
308 :
309 : /* non-null terminated s1 */
310 1 : s1[s1len] = 0x1;
311 1 : err = strcmp_s (s1, s1len, "Simplicity is the ultimate sophistication",
312 : &indicator);
313 1 : if (err != EINVAL)
314 0 : return -1;
315 :
316 : /* OK, seems to work */
317 1 : return 0;
318 : }
319 :
320 : static int
321 1 : test_clib_strcmp (vlib_main_t * vm, unformat_input_t * input)
322 : {
323 1 : char s1[] = "Simplicity is the ultimate sophistication";
324 : int indicator;
325 : char *s;
326 :
327 1 : vlib_cli_output (vm, "Test clib_strcmp...");
328 :
329 : /* s1 == s2, 0 is expected */
330 1 : indicator = clib_strcmp (s1, "Simplicity is the ultimate sophistication");
331 1 : if (indicator != 0)
332 0 : return -1;
333 : /* verify it against strcmp */
334 1 : indicator = strcmp (s1, "Simplicity is the ultimate sophistication");
335 1 : if (indicator != 0)
336 0 : return -1;
337 :
338 : /* s1 > s2, > 0 is expected */
339 1 : indicator = clib_strcmp (s1, "Simplicity is the ultimate");
340 1 : if (!(indicator > 0))
341 0 : return -1;
342 : /* verify it against strcmp */
343 1 : indicator = strcmp (s1, "Simplicity is the ultimate");
344 1 : if (!(indicator > 0))
345 0 : return -1;
346 :
347 : /* s1 < s2, < 0 is expected */
348 1 : indicator = clib_strcmp (s1, "Simplicity is the ultimate sophistication!");
349 1 : if (!(indicator < 0))
350 0 : return -1;
351 : /* verify it against strcmp */
352 1 : indicator = strcmp (s1, "Simplicity is the ultimate sophistication!");
353 1 : if (!(indicator < 0))
354 0 : return -1;
355 :
356 : /* Try some negative tests */
357 :
358 : /* Null pointers comparison */
359 1 : s = 0;
360 1 : indicator = clib_strcmp (s, s);
361 1 : if (indicator != 0)
362 0 : return -1;
363 :
364 : /* OK, seems to work */
365 1 : return 0;
366 : }
367 :
368 : static int
369 1 : test_strncmp_s (vlib_main_t * vm, unformat_input_t * input)
370 : {
371 1 : char s1[] = "Every moment is a fresh beginning";
372 1 : uword s1len = sizeof (s1) - 1; // excluding null
373 : errno_t err;
374 1 : int indicator = 0;
375 :
376 1 : vlib_cli_output (vm, "Test strncmp_s...");
377 :
378 : /* s1 == s2, 0 is expected */
379 1 : err = strncmp_s (s1, s1len, "Every moment is a fresh beginning", s1len,
380 : &indicator);
381 1 : if (err != EOK)
382 0 : return -1;
383 1 : if (indicator != 0)
384 0 : return -1;
385 :
386 : /* s1 > s2, 0 is expected since comparison is no more than n character */
387 1 : err = strncmp_s (s1, s1len, "Every moment is a fresh begin",
388 : sizeof ("Every moment is a fresh begin") - 1, &indicator);
389 1 : if (err != EOK)
390 0 : return -1;
391 1 : if (indicator != 0)
392 0 : return -1;
393 :
394 : /* s1 < s2, < 0 is expected */
395 1 : err = strncmp_s (s1, s1len, "Every moment is fresh beginning",
396 : sizeof ("Every moment is fresh beginning") - 1,
397 : &indicator);
398 1 : if (err != EOK)
399 0 : return -1;
400 1 : if (!(indicator < 0))
401 0 : return -1;
402 :
403 : /* s1 > s2, > 0 is expected */
404 1 : err = strncmp_s ("Every moment is fresh beginning. ",
405 : sizeof ("Every moment is fresh beginning. ") - 1, s1,
406 : s1len, &indicator);
407 1 : if (err != EOK)
408 0 : return -1;
409 1 : if (!(indicator > 0))
410 0 : return -1;
411 :
412 : /* Try some negative tests */
413 :
414 : /* Null pointers */
415 1 : err = strncmp_s (0, 0, 0, 0, 0);
416 1 : if (err != EINVAL)
417 0 : return -1;
418 :
419 : /* n > s1max */
420 1 : err = strncmp_s (s1, s1len, "Every moment is a fresh beginning", s1len + 1,
421 : &indicator);
422 1 : if (err != EINVAL)
423 0 : return -1;
424 :
425 : /* unterminated s1 */
426 1 : s1[s1len] = 0x1;
427 1 : err = strncmp_s (s1, s1len, "Every moment is a fresh beginning",
428 : sizeof ("Every moment is a fresh beginning") - 1,
429 : &indicator);
430 1 : if (err != EINVAL)
431 0 : return -1;
432 :
433 : /* OK, seems to work */
434 1 : return 0;
435 : }
436 :
437 : static int
438 1 : test_clib_strncmp (vlib_main_t * vm, unformat_input_t * input)
439 : {
440 1 : char s1[] = "Every moment is a fresh beginning";
441 1 : uword s1len = sizeof (s1) - 1; // excluding null
442 : int indicator, v_indicator;
443 :
444 1 : vlib_cli_output (vm, "Test clib_strncmp...");
445 :
446 : /* s1 == s2, 0 is expected */
447 1 : indicator = clib_strncmp (s1, "Every moment is a fresh beginning", s1len);
448 1 : if (indicator != 0)
449 0 : return -1;
450 : /* verify it against strncmp */
451 1 : v_indicator = strncmp (s1, "Every moment is a fresh beginning", s1len);
452 1 : if (v_indicator != 0)
453 0 : return -1;
454 :
455 : /* s1 > s2, 0 is expected since comparison is no more than n character */
456 1 : indicator = clib_strncmp (s1, "Every moment is a fresh begin",
457 : sizeof ("Every moment is a fresh begin") - 1);
458 1 : if (indicator != 0)
459 0 : return -1;
460 : /* verify it against strncmp */
461 1 : v_indicator = strncmp (s1, "Every moment is a fresh begin",
462 : sizeof ("Every moment is a fresh begin") - 1);
463 1 : if (v_indicator != 0)
464 0 : return -1;
465 :
466 : /* s1 < s2, < 0 is expected */
467 1 : indicator = clib_strncmp (s1, "Every moment is fresh beginning",
468 : sizeof ("Every moment is fresh beginning") - 1);
469 1 : if (!(indicator < 0))
470 0 : return -1;
471 : /* verify it against strncmp */
472 1 : v_indicator = strncmp (s1, "Every moment is fresh beginning",
473 : sizeof ("Every moment is fresh beginning") - 1);
474 1 : if (!(v_indicator < 0))
475 0 : return -1;
476 1 : if (v_indicator != indicator)
477 0 : return -1;
478 :
479 : /* s1 > s2, > 0 is expected */
480 1 : indicator = clib_strncmp ("Every moment is fresh beginning. ", s1, s1len);
481 1 : if (!(indicator > 0))
482 0 : return -1;
483 : /* verify it against strncmp */
484 1 : v_indicator = strncmp ("Every moment is fresh beginning. ", s1, s1len);
485 1 : if (!(v_indicator > 0))
486 0 : return -1;
487 1 : if (v_indicator != indicator)
488 0 : return -1;
489 :
490 : /* Try some negative tests */
491 :
492 : /* Null pointers */
493 :
494 : /* make sure we don't crash */
495 1 : indicator = clib_strncmp (0, 0, 0);
496 1 : if (indicator != EOK)
497 0 : return -1;
498 :
499 : /* n > s1 len */
500 1 : indicator =
501 1 : clib_strncmp (s1, "Every moment is a fresh beginning", s1len + 1);
502 1 : if (indicator != 0)
503 0 : return -1;
504 : /* verify it against strncmp */
505 1 : v_indicator = strncmp (s1, "Every moment is a fresh beginning", s1len + 1);
506 1 : if (v_indicator != 0)
507 0 : return -1;
508 :
509 : /* unterminated s1 */
510 1 : s1[s1len] = 0x1;
511 1 : clib_mem_unpoison (s1, CLIB_STRING_MACRO_MAX);
512 1 : indicator = clib_strncmp (s1, "Every moment is a fresh beginning",
513 : sizeof ("every moment is a fresh beginning") - 1);
514 1 : if (indicator != 0)
515 0 : return -1;
516 : /* verify it against strncmp */
517 1 : v_indicator = strncmp (s1, "Every moment is a fresh beginning",
518 : sizeof ("Every moment is a fresh beginning") - 1);
519 1 : if (v_indicator != 0)
520 0 : return -1;
521 :
522 : /* OK, seems to work */
523 1 : return 0;
524 : }
525 :
526 : static int
527 1 : test_strcpy_s (vlib_main_t * vm, unformat_input_t * input)
528 : {
529 1 : char src[] = "To err is human.";
530 : char dst[64];
531 : int indicator;
532 1 : size_t s1size = sizeof (dst); // including null
533 : errno_t err;
534 :
535 1 : vlib_cli_output (vm, "Test strcpy_s...");
536 :
537 1 : err = strcpy_s (dst, s1size, src);
538 1 : if (err != EOK)
539 0 : return -1;
540 :
541 : /* This better not fail but check anyhow */
542 1 : if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), src, &indicator) !=
543 : EOK)
544 0 : return -1;
545 1 : if (indicator != 0)
546 0 : return -1;
547 :
548 : /* Negative tests */
549 :
550 1 : err = strcpy_s (0, 0, 0);
551 1 : if (err == EOK)
552 0 : return -1;
553 :
554 : /* Size fail */
555 1 : err = strcpy_s (dst, 10, src);
556 1 : if (err == EOK)
557 0 : return -1;
558 :
559 : /* overlap fail */
560 : #if __GNUC__ < 8
561 : /* GCC 8 flunks this one at compile time... */
562 : err = strcpy_s (dst, s1size, dst);
563 : if (err == EOK)
564 : return -1;
565 : #endif
566 :
567 : /* overlap fail */
568 1 : err = strcpy_s (dst, s1size, dst + 1);
569 1 : if (err == EOK)
570 0 : return -1;
571 :
572 : /* OK, seems to work */
573 1 : return 0;
574 : }
575 :
576 : static int
577 1 : test_strncpy_s (vlib_main_t * vm, unformat_input_t * input)
578 : {
579 1 : char src[] = "Those who dare to fail miserably can achieve greatly.";
580 : char dst[100], old_dst[100];
581 : int indicator, i;
582 1 : size_t s1size = sizeof (dst); // including null
583 : errno_t err;
584 :
585 1 : vlib_cli_output (vm, "Test strncpy_s...");
586 :
587 : /* dmax includes null, n excludes null */
588 :
589 : /* n == string len of src */
590 1 : err = strncpy_s (dst, s1size, src, clib_strnlen (src, sizeof (src)));
591 1 : if (err != EOK)
592 0 : return -1;
593 1 : if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), src, &indicator) !=
594 : EOK)
595 0 : return -1;
596 1 : if (indicator != 0)
597 0 : return -1;
598 :
599 : /* limited copy -- strlen src > n, copy up to n */
600 1 : err = strncpy_s (dst, s1size, "The price of greatness is responsibility.",
601 : 10);
602 1 : if (err != EOK)
603 0 : return -1;
604 1 : if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), "The price ",
605 : &indicator) != EOK)
606 0 : return -1;
607 1 : if (indicator != 0)
608 0 : return -1;
609 :
610 : /* n > string len of src */
611 1 : err = clib_memset (dst, 1, sizeof (dst));
612 1 : if (err != EOK)
613 0 : return -1;
614 :
615 1 : err = strncpy_s (dst, s1size, src, clib_strnlen (src, sizeof (src)) + 10);
616 1 : if (err != EOK)
617 0 : return -1;
618 1 : if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), src, &indicator) !=
619 : EOK)
620 0 : return -1;
621 1 : if (indicator != 0)
622 0 : return -1;
623 :
624 : /* Make sure bytes after strlen(dst) is untouched */
625 47 : for (i = 1 + clib_strnlen (dst, sizeof (dst)); i < sizeof (dst); i++)
626 46 : if (dst[i] != 1)
627 0 : return -1;
628 :
629 : /* truncation, n >= dmax */
630 1 : err = strncpy_s (dst, clib_strnlen (src, sizeof (src)), src,
631 : clib_strnlen (src, sizeof (src)));
632 1 : if (err != EOVERFLOW)
633 0 : return -1;
634 :
635 : /* Check dst content */
636 1 : if (dst[strlen (dst)] != '\0')
637 0 : return -1;
638 1 : if (strncmp_s (dst, clib_strnlen (dst, sizeof (dst)), src,
639 : clib_strnlen (dst, sizeof (dst)), &indicator) != EOK)
640 0 : return -1;
641 1 : if (indicator != 0)
642 0 : return -1;
643 :
644 : /* zero length copy */
645 1 : clib_strncpy (old_dst, dst, clib_strnlen (dst, sizeof (dst)));
646 1 : err = strncpy_s (dst, sizeof (dst), src, 0);
647 1 : if (err != EOK)
648 0 : return -1;
649 : /* verify dst is untouched */
650 1 : if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), old_dst, &indicator) !=
651 : EOK)
652 0 : return -1;
653 1 : if (indicator != 0)
654 0 : return -1;
655 :
656 : /* Negative tests */
657 :
658 1 : err = strncpy_s (0, 0, 0, 1);
659 1 : if (err == EOK)
660 0 : return -1;
661 :
662 : /* overlap fail */
663 1 : err = strncpy_s (dst, s1size, dst + 1, s1size - 1);
664 1 : if (err == EOK)
665 0 : return -1;
666 :
667 : /* overlap fail */
668 : #if __GNUC__ < 8
669 : /* GCC 8 flunks this one at compile time... */
670 : err = strncpy_s (dst, s1size, dst, s1size);
671 : if (err == EOK)
672 : return -1;
673 : #endif
674 :
675 : /* OK, seems to work */
676 1 : return 0;
677 : }
678 :
679 : static int
680 1 : test_clib_strncpy (vlib_main_t * vm, unformat_input_t * input)
681 : {
682 1 : char src[] = "Those who dare to fail miserably can achieve greatly.";
683 : char dst[100], old_dst[100];
684 : int indicator;
685 1 : size_t s1size = sizeof (dst); // including null
686 : errno_t err;
687 :
688 1 : vlib_cli_output (vm, "Test clib_strncpy...");
689 :
690 : /* n == string len of src */
691 1 : err = clib_strncpy (dst, src, clib_strnlen (src, sizeof (src)));
692 1 : if (err != EOK)
693 0 : return -1;
694 :
695 : /* This better not fail but check anyhow */
696 1 : if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), src, &indicator) !=
697 : EOK)
698 0 : return -1;
699 1 : if (indicator != 0)
700 0 : return -1;
701 :
702 : /* Verify it against strncpy */
703 : #if __GNUC__ < 8
704 : /* GCC 8 debian flunks this one at compile time */
705 : strncpy (dst, src, strlen (src));
706 :
707 : /* This better not fail but check anyhow */
708 : if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), src, &indicator) !=
709 : EOK)
710 : return -1;
711 : if (indicator != 0)
712 : return -1;
713 : #endif
714 :
715 : /* limited copy -- strlen src > n, copy up to n */
716 1 : err = clib_strncpy (dst, "The price of greatness is responsibility.", 10);
717 1 : if (err != EOK)
718 0 : return -1;
719 1 : if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), "The price ",
720 : &indicator) != EOK)
721 0 : return -1;
722 1 : if (indicator != 0)
723 0 : return -1;
724 : /* verify it against strncpy */
725 1 : memset_s (dst, sizeof (dst), 0, sizeof (dst));
726 :
727 : #if __GNUC__ < 8
728 : /* GCC 8 flunks this one at compile time... */
729 : strncpy (dst, "The price of greatness is responsibility.", 10);
730 : if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), "The price ",
731 : &indicator) != EOK)
732 : return -1;
733 : if (indicator != 0)
734 : return -1;
735 : #endif
736 :
737 : /* n > string len of src */
738 1 : err = clib_strncpy (dst, src, clib_strnlen (src, sizeof (src)) + 10);
739 1 : if (err != EOK)
740 0 : return -1;
741 1 : if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), src, &indicator) !=
742 : EOK)
743 0 : return -1;
744 1 : if (indicator != 0)
745 0 : return -1;
746 : /* Verify it against strncpy */
747 : #if __GNUC__ < 8
748 : /* GCC 8 debian flunks this one at compile time */
749 : strncpy (dst, src, strlen (src));
750 : if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), src, &indicator) !=
751 : EOK)
752 : return -1;
753 : if (indicator != 0)
754 : return -1;
755 : #endif
756 :
757 : /* zero length copy */
758 1 : clib_strncpy (old_dst, dst, clib_strnlen (dst, sizeof (dst)));
759 1 : err = clib_strncpy (dst, src, 0);
760 1 : if (err != EOK)
761 0 : return -1;
762 : /* verify dst is untouched */
763 1 : if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), old_dst, &indicator) !=
764 : EOK)
765 0 : return -1;
766 1 : if (indicator != 0)
767 0 : return -1;
768 :
769 : /* Negative tests */
770 :
771 1 : err = clib_strncpy (0, 0, 1);
772 1 : if (err == EOK)
773 0 : return -1;
774 :
775 : /* overlap fail */
776 1 : err = clib_strncpy (dst, dst + 1, s1size);
777 1 : if (err == EOK)
778 0 : return -1;
779 :
780 : /* overlap fail */
781 : #if __GNUC__ < 8
782 : /* GCC 8 flunks this one at compile time... */
783 : err = clib_strncpy (dst, dst, s1size);
784 : if (err == EOK)
785 : return -1;
786 : #endif
787 :
788 : /* OK, seems to work */
789 1 : return 0;
790 : }
791 :
792 : static int
793 1 : test_strcat_s (vlib_main_t * vm, unformat_input_t * input)
794 : {
795 : char src[100], dst[100], old_dst[100];
796 1 : size_t s1size = sizeof (dst); // including null
797 : errno_t err;
798 : int indicator;
799 :
800 1 : vlib_cli_output (vm, "Test strcat_s...");
801 :
802 1 : strcpy_s (dst, sizeof (dst), "Tough time never last ");
803 1 : strcpy_s (src, sizeof (src), "but tough people do");
804 1 : err = strcat_s (dst, s1size, src);
805 1 : if (err != EOK)
806 0 : return -1;
807 1 : if (strcmp_s (dst, s1size - 1,
808 : "Tough time never last but tough people do",
809 : &indicator) != EOK)
810 0 : return -1;
811 1 : if (indicator != 0)
812 0 : return -1;
813 :
814 : /* empty string concatenation */
815 1 : clib_strncpy (old_dst, dst, clib_strnlen (dst, sizeof (dst)));
816 1 : err = strcat_s (dst, s1size, "");
817 1 : if (err != EOK)
818 0 : return -1;
819 : /* verify dst is untouched */
820 1 : if (strcmp_s (dst, s1size - 1, old_dst, &indicator) != EOK)
821 0 : return -1;
822 1 : if (indicator != 0)
823 0 : return -1;
824 :
825 : /* negative stuff */
826 1 : err = strcat_s (0, 0, 0);
827 1 : if (err != EINVAL)
828 0 : return -1;
829 :
830 : /* overlap fail */
831 1 : err = strcat_s (dst, s1size, dst + 1);
832 1 : if (err != EINVAL)
833 0 : return -1;
834 :
835 : /* overlap fail */
836 : #if __GNUC__ < 8
837 : /* GCC 8 flunks this one at compile time... */
838 : err = strcat_s (dst, s1size, dst);
839 : if (err != EINVAL)
840 : return -1;
841 : #endif
842 :
843 : /* not enough space for dst */
844 1 : err = strcat_s (dst, 10, src);
845 1 : if (err != EINVAL)
846 0 : return -1;
847 :
848 : /* OK, seems to work */
849 1 : return 0;
850 : }
851 :
852 : static int
853 1 : test_strncat_s (vlib_main_t * vm, unformat_input_t * input)
854 : {
855 : char src[100], dst[100], old_dst[100];
856 1 : size_t s1size = sizeof (dst); // including null
857 : errno_t err;
858 1 : char s1[] = "Two things are infinite: ";
859 1 : char s2[] = "the universe and human stupidity; ";
860 1 : char s3[] = "I am not sure about the universe.";
861 : int indicator;
862 :
863 1 : vlib_cli_output (vm, "Test strncat_s...");
864 :
865 1 : strcpy_s (dst, sizeof (dst), s1);
866 1 : strcpy_s (src, sizeof (src), s2);
867 1 : err = strncat_s (dst, s1size, src, clib_strnlen (src, sizeof (src)));
868 1 : if (err != EOK)
869 0 : return -1;
870 1 : if (strcmp_s (dst, s1size - 1,
871 : "Two things are infinite: the universe and human stupidity; ",
872 : &indicator) != EOK)
873 0 : return -1;
874 1 : if (indicator != 0)
875 0 : return -1;
876 :
877 : /* truncation, n >= dmax - strnlen_s (dst, dmax) */
878 2 : err = strncat_s (dst, clib_strnlen (dst, sizeof (dst)) +
879 1 : clib_strnlen (s3, sizeof (s3)), s3,
880 : clib_strnlen (s3, sizeof (s3)));
881 1 : if (err != EOVERFLOW)
882 0 : return -1;
883 : /*
884 : * resulting string is dst + strlen (s3) - 1 characters + null.
885 : * notice the "." is missing at the end of the resulting string because
886 : * the space is needed to accommodate the null
887 : * Notice strcmp_s will check s1 or dst to make sure it is null terminated
888 : */
889 1 : if (strcmp_s (dst, s1size - 1,
890 : "Two things are infinite: the universe and human stupidity; "
891 : "I am not sure about the universe", &indicator) != EOK)
892 0 : return -1;
893 1 : if (indicator != 0)
894 0 : return -1;
895 :
896 : /* n > strlen src */
897 1 : strcpy_s (dst, sizeof (dst), s1);
898 1 : err = strncat_s (dst, s1size, src, clib_strnlen (src, sizeof (src)) + 10);
899 1 : if (err != EOK)
900 0 : return -1;
901 1 : if (strcmp_s (dst, s1size - 1,
902 : "Two things are infinite: the universe and human stupidity; ",
903 : &indicator) != EOK)
904 0 : return -1;
905 1 : if (indicator != 0)
906 0 : return -1;
907 :
908 : /* zero length strncat */
909 1 : clib_strncpy (old_dst, dst, clib_strnlen (dst, sizeof (dst)));
910 1 : err = strncat_s (dst, sizeof (dst), src, 0);
911 1 : if (err != EOK)
912 0 : return -1;
913 : /* verify dst is untouched */
914 1 : if (strcmp_s (dst, s1size - 1, old_dst, &indicator) != EOK)
915 0 : return -1;
916 1 : if (indicator != 0)
917 0 : return -1;
918 :
919 : /* empty string, wrong n concatenation */
920 1 : err = strncat_s (dst, sizeof (dst), "", 10);
921 1 : if (err != EOK)
922 0 : return -1;
923 : /* verify dst is untouched */
924 1 : if (strcmp_s (dst, s1size - 1, old_dst, &indicator) != EOK)
925 0 : return -1;
926 1 : if (indicator != 0)
927 0 : return -1;
928 :
929 : /* limited concatenation, string > n, copy up to n */
930 1 : strcpy_s (dst, sizeof (dst), s1);
931 1 : err = strncat_s (dst, s1size, s2, 13);
932 1 : if (err != EOK)
933 0 : return -1;
934 1 : if (strcmp_s (dst, s1size - 1, "Two things are infinite: the universe ",
935 : &indicator) != EOK)
936 0 : return -1;
937 1 : if (indicator != 0)
938 0 : return -1;
939 : /* verify it against strncat */
940 : #if __GNUC__ < 8
941 : /* GCC 8 debian flunks this one at compile time */
942 : strcpy_s (dst, sizeof (dst), s1);
943 : strncat (dst, s2, 13);
944 : if (strcmp_s (dst, s1size - 1, "Two things are infinite: the universe ",
945 : &indicator) != EOK)
946 : return -1;
947 : if (indicator != 0)
948 : return -1;
949 : #endif
950 :
951 : /* negative stuff */
952 1 : err = strncat_s (0, 0, 0, 1);
953 1 : if (err != EINVAL)
954 0 : return -1;
955 :
956 : /* no room for dst -- dmax - strnlen_s (dst, dmax) == 0 */
957 1 : err = strncat_s (dst, clib_strnlen (dst, sizeof (dst)), s2,
958 : clib_strnlen (s2, sizeof (s2)));
959 1 : if (err != EINVAL)
960 0 : return -1;
961 :
962 : /* overlap fail */
963 1 : err = strncat_s (dst, s1size, dst + 1, clib_strnlen (dst + 1, s1size - 1));
964 1 : if (err != EINVAL)
965 0 : return -1;
966 :
967 : /* overlap fail */
968 : #if __GNUC__ < 8
969 : /* GCC 8 flunks this one at compile time... */
970 : err = strncat_s (dst, s1size, dst, clib_strnlen (dst, sizeof (dst)));
971 : if (err != EINVAL)
972 : return -1;
973 : #endif
974 :
975 : /* OK, seems to work */
976 1 : return 0;
977 : }
978 :
979 : static int
980 1 : test_strtok_s (vlib_main_t * vm, unformat_input_t * input)
981 : {
982 : int indicator;
983 : char *tok, *ptr;
984 : char str2[20];
985 : char str1[40];
986 : uword len;
987 1 : char *p2str = 0;
988 : char *tok1, *tok2, *tok3, *tok4, *tok5, *tok6, *tok7;
989 :
990 1 : vlib_cli_output (vm, "Test strtok_s...");
991 1 : strcpy_s (str1, sizeof (str1), "brevity is the soul of wit");
992 1 : len = strnlen_s (str1, sizeof (str1));
993 1 : tok1 = strtok_s (str1, &len, " ", &p2str);
994 1 : tok2 = strtok_s (0, &len, " ", &p2str);
995 1 : tok3 = strtok_s (0, &len, " ", &p2str);
996 1 : tok4 = strtok_s (0, &len, " ", &p2str);
997 1 : tok5 = strtok_s (0, &len, " ", &p2str);
998 1 : tok6 = strtok_s (0, &len, " ", &p2str);
999 1 : tok7 = strtok_s (0, &len, " ", &p2str);
1000 2 : if ((tok1 == 0) ||
1001 1 : strcmp_s (tok1, strlen (tok1), "brevity", &indicator) != EOK)
1002 0 : return -1;
1003 1 : if (indicator != 0)
1004 0 : return -1;
1005 1 : if ((tok2 == 0) || strcmp_s (tok2, strlen (tok2), "is", &indicator) != EOK)
1006 0 : return -1;
1007 1 : if (indicator != 0)
1008 0 : return -1;
1009 1 : if ((tok3 == 0) || strcmp_s (tok3, strlen (tok3), "the", &indicator) != EOK)
1010 0 : return -1;
1011 1 : if (indicator != 0)
1012 0 : return -1;
1013 1 : if ((tok4 == 0)
1014 1 : || strcmp_s (tok4, strlen (tok4), "soul", &indicator) != EOK)
1015 0 : return -1;
1016 1 : if (indicator != 0)
1017 0 : return -1;
1018 1 : if ((tok5 == 0) || strcmp_s (tok5, strlen (tok5), "of", &indicator) != EOK)
1019 0 : return -1;
1020 1 : if (indicator != 0)
1021 0 : return -1;
1022 1 : if ((tok6 == 0) || strcmp_s (tok6, strlen (tok6), "wit", &indicator) != EOK)
1023 0 : return -1;
1024 1 : if (indicator != 0)
1025 0 : return -1;
1026 1 : if (tok7 != 0)
1027 0 : return -1;
1028 :
1029 : /* delimiter not present in the string -- the whole string is returned */
1030 1 : strcpy_s (str1, sizeof (str1), "brevity is the soul of wit");
1031 1 : len = strnlen_s (str1, sizeof (str1) - 1);
1032 1 : p2str = 0;
1033 1 : tok1 = strtok_s (str1, &len, ",", &p2str);
1034 1 : if ((tok1 == 0) || strcmp_s (tok1, strlen (tok1), str1, &indicator) != EOK)
1035 0 : return -1;
1036 1 : if (indicator != 0)
1037 0 : return -1;
1038 :
1039 : /* negative stuff */
1040 1 : tok = strtok_s (0, 0, 0, 0);
1041 1 : if (tok != 0)
1042 0 : return -1;
1043 :
1044 : /* s1 and ptr contents are null */
1045 1 : ptr = 0;
1046 1 : tok = strtok_s (0, 0, 0, &ptr);
1047 1 : if (tok != 0)
1048 0 : return -1;
1049 :
1050 : /* unterminate s1 */
1051 1 : p2str = 0;
1052 1 : len = strnlen_s (str1, sizeof (str1) - 1);
1053 1 : str1[strlen (str1)] = 0x2;
1054 1 : tok = strtok_s (str1, &len, ",", &p2str);
1055 1 : if (tok != 0)
1056 0 : return -1;
1057 :
1058 : /*
1059 : * unterminated s2. This test case in not perfect because there is no
1060 : * argument for s2max. But s2 len is limited to 16 characters. If the API
1061 : * does not find the null character at s2[15], it declares the string s2
1062 : * as unterminated.
1063 : */
1064 1 : memset_s (str2, sizeof (str2), 0xfa, sizeof (str2));
1065 1 : tok = strtok_s (str1, &len, str2, &p2str);
1066 1 : if (tok != 0)
1067 0 : return -1;
1068 :
1069 : /* OK, seems to work */
1070 1 : return 0;
1071 : }
1072 :
1073 : static int
1074 1 : test_clib_strtok (vlib_main_t * vm, unformat_input_t * input)
1075 : {
1076 : int indicator;
1077 : char *s1 __attribute__ ((unused));
1078 : char *tok __attribute__ ((unused));
1079 : char *ptr __attribute__ ((unused));
1080 : char str1[40];
1081 : char *p2str;
1082 : char *tok1, *tok2, *tok3, *tok4, *tok5, *tok6, *tok7;
1083 :
1084 1 : vlib_cli_output (vm, "Test clib_strtok...");
1085 1 : strcpy_s (str1, sizeof (str1), "brevity is the soul of wit");
1086 1 : p2str = 0;
1087 1 : tok1 = clib_strtok (str1, " ", &p2str);
1088 1 : tok2 = clib_strtok (0, " ", &p2str);
1089 1 : tok3 = clib_strtok (0, " ", &p2str);
1090 1 : tok4 = clib_strtok (0, " ", &p2str);
1091 1 : tok5 = clib_strtok (0, " ", &p2str);
1092 1 : tok6 = clib_strtok (0, " ", &p2str);
1093 1 : tok7 = clib_strtok (0, " ", &p2str);
1094 2 : if ((tok1 == 0) ||
1095 1 : strcmp_s (tok1, strlen (tok1), "brevity", &indicator) != EOK)
1096 0 : return -1;
1097 1 : if (indicator != 0)
1098 0 : return -1;
1099 1 : if ((tok2 == 0) || strcmp_s (tok2, strlen (tok2), "is", &indicator) != EOK)
1100 0 : return -1;
1101 1 : if (indicator != 0)
1102 0 : return -1;
1103 1 : if ((tok3 == 0) || strcmp_s (tok3, strlen (tok3), "the", &indicator) != EOK)
1104 0 : return -1;
1105 1 : if (indicator != 0)
1106 0 : return -1;
1107 1 : if ((tok4 == 0)
1108 1 : || strcmp_s (tok4, strlen (tok4), "soul", &indicator) != EOK)
1109 0 : return -1;
1110 1 : if (indicator != 0)
1111 0 : return -1;
1112 1 : if ((tok5 == 0) || strcmp_s (tok5, strlen (tok5), "of", &indicator) != EOK)
1113 0 : return -1;
1114 1 : if (indicator != 0)
1115 0 : return -1;
1116 1 : if ((tok6 == 0) || strcmp_s (tok6, strlen (tok6), "wit", &indicator) != EOK)
1117 0 : return -1;
1118 1 : if (indicator != 0)
1119 0 : return -1;
1120 1 : if (tok7 != 0)
1121 0 : return -1;
1122 : /* verify it againest strtok_r */
1123 1 : strcpy_s (str1, sizeof (str1), "brevity is the soul of wit");
1124 1 : p2str = 0;
1125 1 : tok1 = strtok_r (str1, " ", &p2str);
1126 1 : tok2 = strtok_r (0, " ", &p2str);
1127 1 : tok3 = strtok_r (0, " ", &p2str);
1128 1 : tok4 = strtok_r (0, " ", &p2str);
1129 1 : tok5 = strtok_r (0, " ", &p2str);
1130 1 : tok6 = strtok_r (0, " ", &p2str);
1131 1 : tok7 = strtok_r (0, " ", &p2str);
1132 2 : if ((tok1 == 0) ||
1133 1 : strcmp_s (tok1, strlen (tok1), "brevity", &indicator) != EOK)
1134 0 : return -1;
1135 1 : if (indicator != 0)
1136 0 : return -1;
1137 1 : if ((tok2 == 0) || strcmp_s (tok2, strlen (tok2), "is", &indicator) != EOK)
1138 0 : return -1;
1139 1 : if (indicator != 0)
1140 0 : return -1;
1141 1 : if ((tok3 == 0) || strcmp_s (tok3, strlen (tok3), "the", &indicator) != EOK)
1142 0 : return -1;
1143 1 : if (indicator != 0)
1144 0 : return -1;
1145 1 : if ((tok4 == 0)
1146 1 : || strcmp_s (tok4, strlen (tok4), "soul", &indicator) != EOK)
1147 0 : return -1;
1148 1 : if (indicator != 0)
1149 0 : return -1;
1150 1 : if ((tok5 == 0) || strcmp_s (tok5, strlen (tok5), "of", &indicator) != EOK)
1151 0 : return -1;
1152 1 : if (indicator != 0)
1153 0 : return -1;
1154 1 : if ((tok6 == 0) || strcmp_s (tok6, strlen (tok6), "wit", &indicator) != EOK)
1155 0 : return -1;
1156 1 : if (indicator != 0)
1157 0 : return -1;
1158 1 : if (tok7 != 0)
1159 0 : return -1;
1160 :
1161 : /* delimiter not present in the string -- the whole string is returned */
1162 1 : strcpy_s (str1, sizeof (str1), "brevity is the soul of wit");
1163 1 : p2str = 0;
1164 1 : tok1 = clib_strtok (str1, ",", &p2str);
1165 1 : if ((tok1 == 0) || strcmp_s (tok1, strlen (tok1), str1, &indicator) != EOK)
1166 0 : return -1;
1167 1 : if (indicator != 0)
1168 0 : return -1;
1169 : /* verify it against strtok_r */
1170 1 : strcpy_s (str1, sizeof (str1), "brevity is the soul of wit");
1171 1 : p2str = 0;
1172 1 : tok1 = strtok_r (str1, ",", &p2str);
1173 1 : if ((tok1 == 0) || strcmp_s (tok1, strlen (tok1), str1, &indicator) != EOK)
1174 0 : return -1;
1175 1 : if (indicator != 0)
1176 0 : return -1;
1177 :
1178 : /* negative stuff */
1179 1 : s1 = 0;
1180 1 : ptr = 0;
1181 : #if __GNUC__ < 8
1182 : /* GCC 8 flunks this one at compile time... */
1183 : tok = clib_strtok (s1, s1, (char **) 0);
1184 : if (tok != 0)
1185 : return -1;
1186 :
1187 : /* s1 and ptr contents are null */
1188 : tok = clib_strtok (s1, s1, &ptr);
1189 : if (tok != 0)
1190 : return -1;
1191 : #endif
1192 :
1193 : /* verify it against strtok_r */
1194 : /* No can do. This causes a crash in strtok_r */
1195 : // tok = strtok_r (s1, " ", &ptr);
1196 : // if (tok != 0)
1197 : // return -1;
1198 :
1199 : /*
1200 : * Can't test unterminated string s1 and s2 becuase clib_strtok does not
1201 : * supply s1 and s2 max
1202 : */
1203 :
1204 : /* OK, seems to work */
1205 1 : return 0;
1206 : }
1207 :
1208 : static int
1209 1 : test_strnlen_s (vlib_main_t * vm, unformat_input_t * input)
1210 : {
1211 1 : const char s1[] = "Truth is incontrovertible";
1212 : size_t len;
1213 :
1214 1 : vlib_cli_output (vm, "Test strnlen_s...");
1215 :
1216 1 : len = strnlen_s (s1, sizeof (s1));
1217 1 : if (len != sizeof (s1) - 1)
1218 0 : return -1;
1219 :
1220 1 : len = strnlen_s (s1, 5);
1221 1 : if (len != 5)
1222 0 : return -1;
1223 :
1224 : /* negative stuff */
1225 1 : len = strnlen_s (0, 0);
1226 1 : if (len != 0)
1227 0 : return -1;
1228 :
1229 : /* OK, seems to work */
1230 1 : return 0;
1231 : }
1232 :
1233 : static int
1234 1 : test_clib_strnlen (vlib_main_t * vm, unformat_input_t * input)
1235 : {
1236 1 : const char s1[] = "Truth is incontrovertible";
1237 : size_t len;
1238 :
1239 1 : vlib_cli_output (vm, "Test clib_strnlen...");
1240 :
1241 1 : len = clib_strnlen (s1, sizeof (s1));
1242 1 : if (len != sizeof (s1) - 1)
1243 0 : return -1;
1244 :
1245 1 : len = clib_strnlen (s1, 5);
1246 1 : if (len != 5)
1247 0 : return -1;
1248 :
1249 : /* negative stuff */
1250 1 : len = clib_strnlen (0, 0);
1251 1 : if (len != 0)
1252 0 : return -1;
1253 :
1254 : /* OK, seems to work */
1255 1 : return 0;
1256 : }
1257 :
1258 : static int
1259 1 : test_strstr_s (vlib_main_t * vm, unformat_input_t * input)
1260 : {
1261 : errno_t err;
1262 1 : char *sub = 0;
1263 : char s1[64];
1264 1 : size_t s1len = sizeof (s1) - 1; // excluding null
1265 : int indicator;
1266 :
1267 1 : vlib_cli_output (vm, "Test strstr_s...");
1268 :
1269 : /* substring not present */
1270 1 : strcpy_s (s1, s1len, "success is not final, failure is not fatal.");
1271 1 : err = strstr_s (s1, s1len, "failures", sizeof ("failures"), &sub);;
1272 1 : if (err != ESRCH)
1273 0 : return -1;
1274 :
1275 : /* substring present */
1276 1 : err = strstr_s (s1, s1len, "failure", sizeof ("failure"), &sub);
1277 1 : if (err != EOK)
1278 0 : return -1;
1279 :
1280 2 : if ((sub == 0) ||
1281 1 : strcmp_s (sub, strlen (sub), "failure is not fatal.", &indicator)
1282 : != EOK)
1283 0 : return -1;
1284 1 : if (indicator != 0)
1285 0 : return -1;
1286 :
1287 : /* negative stuff */
1288 :
1289 : /* Null pointers test */
1290 1 : err = strstr_s (0, 0, 0, 0, 0);
1291 1 : if (err != EINVAL)
1292 0 : return -1;
1293 :
1294 : /* unterminated s1 and s2 */
1295 1 : memset_s (s1, ARRAY_LEN (s1), 0xfe, ARRAY_LEN (s1));
1296 1 : err = strstr_s (s1, s1len, s1, s1len, &sub);
1297 1 : if (err != EINVAL)
1298 0 : return -1;
1299 :
1300 : /* OK, seems to work */
1301 1 : return 0;
1302 : }
1303 :
1304 : #define foreach_string_test \
1305 : _ (0, MEMCPY_S, "memcpy_s", memcpy_s) \
1306 : _ (1, CLIB_MEMCPY, "clib_memcpy", clib_memcpy) \
1307 : _ (2, MEMSET_S, "memset_s", memset_s) \
1308 : _ (3, CLIB_MEMSET, "clib_memset", clib_memset) \
1309 : _ (4, MEMCMP_S, "memcmp_s", memcmp_s) \
1310 : _ (5, CLIB_MEMCMP, "clib_memcmp", clib_memcmp) \
1311 : _ (6, STRCMP_S, "strcmp_s", strcmp_s) \
1312 : _ (7, CLIB_STRCMP, "clib_strcmp", clib_strcmp) \
1313 : _ (8, STRNCMP_S, "strncmp_s", strncmp_s) \
1314 : _ (9, CLIB_STRNCMP, "clib_strncmp", clib_strncmp) \
1315 : _ (10, STRCPY_S, "strcpy_s", strcpy_s) \
1316 : _ (11, STRNCPY_S, "strncpy_s", strncpy_s) \
1317 : _ (12, CLIB_STRNCPY, "clib_strncpy", clib_strncpy) \
1318 : _ (13, STRCAT_S, "strcat_s", strcat_s) \
1319 : _ (14, STRNCAT_S, "strncat_s", strncat_s) \
1320 : _ (15, STRTOK_S, "strtok_s", strtok_s) \
1321 : _ (16, CLIB_STRTOK, "clib_strtok", clib_strtok) \
1322 : _ (17, STRNLEN_S, "strnlen_s", strnlen_s) \
1323 : _ (18, CLIB_STRNLEN, "clib_strnlen", clib_strnlen) \
1324 : _ (19, STRSTR_S, "strstr_s", strstr_s)
1325 :
1326 : typedef enum
1327 : {
1328 : #define _(v,f,s,p) STRING_TEST_##f = v,
1329 : foreach_string_test
1330 : #undef _
1331 : #define STRING_TEST_FIRST STRING_TEST_MEMCPY_S
1332 : #define STRING_TEST_LAST STRING_TEST_STRSTR_S
1333 : } string_test_t;
1334 :
1335 : static uword
1336 21 : unformat_string_test (unformat_input_t * input, va_list * args)
1337 : {
1338 21 : u8 *r = va_arg (*args, u8 *);
1339 :
1340 : if (0)
1341 : ;
1342 : #define _(v,f,s,p) else if (unformat (input, s)) *r = STRING_TEST_##f;
1343 21 : foreach_string_test
1344 : #undef _
1345 : else
1346 0 : return 0;
1347 :
1348 21 : return 1;
1349 : }
1350 :
1351 : typedef int (*string_test_func) (vlib_main_t * vm, unformat_input_t * input);
1352 :
1353 : typedef struct
1354 : {
1355 : string_test_func test;
1356 : } string_test_func_t;
1357 :
1358 : static clib_error_t *
1359 21 : string_test_command_fn (vlib_main_t * vm,
1360 : unformat_input_t * input,
1361 : vlib_cli_command_t * cmd_arg)
1362 : {
1363 21 : string_test_func_t string_func[] = {
1364 : #define _(v,f,s,p) { test_##p },
1365 : foreach_string_test
1366 : #undef _
1367 : };
1368 21 : const char *string_table[] = {
1369 : #define _(v,f,s,p) s,
1370 : foreach_string_test
1371 : #undef _
1372 : };
1373 21 : int res = 0, ok;
1374 21 : i8 specific_test = ~0;
1375 :
1376 21 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1377 : {
1378 21 : if (unformat (input, "%U", unformat_string_test, &specific_test))
1379 21 : break;
1380 : else
1381 0 : return clib_error_return (0, "unknown input `%U'",
1382 : format_unformat_error, input);
1383 : }
1384 :
1385 21 : if (specific_test == ~0)
1386 : {
1387 0 : for (specific_test = STRING_TEST_FIRST;
1388 0 : specific_test <= STRING_TEST_LAST; specific_test++)
1389 : {
1390 0 : ok = (string_func[specific_test]).test (vm, input);
1391 0 : res += ok;
1392 0 : if (ok != 0)
1393 0 : vlib_cli_output (vm, "test_%s failed",
1394 : string_table[specific_test]);
1395 : }
1396 : }
1397 : else
1398 21 : res = (string_func[specific_test]).test (vm, input);
1399 21 : if (res)
1400 0 : vlib_cli_output (vm, "String unit test(s) failed...");
1401 : else
1402 21 : vlib_cli_output (vm, "String unit test(s) OK...");
1403 21 : return 0;
1404 : }
1405 :
1406 : /* *INDENT-OFF* */
1407 16239 : VLIB_CLI_COMMAND (string_test_command, static) = {
1408 : .path = "test string",
1409 : .short_help =
1410 : "test string [memcpy_s | clib_memcpy | memset_s | "
1411 : "clib_memset | memcmp_s | clib_memcmp | strcmp_s | clib_strcmp | "
1412 : "strncmp_s | clib_strncmp | strcpy_s | strncpy_s | "
1413 : "clib_strncpy | strcat_s | strncat_s | "
1414 : "strtok_s | clib_strtok | strnlen_s | clib_strnlen | strstr_s ]",
1415 : .function = string_test_command_fn,
1416 : };
1417 : /* *INDENT-ON* */
1418 :
1419 : /*
1420 : * fd.io coding-style-patch-verification: ON
1421 : *
1422 : * Local Variables:
1423 : * eval: (c-set-style "gnu")
1424 : * End:
1425 : */
|