virtio: Add RX queue full statisitics
[vpp.git] / src / vppinfra / string.h
1 /*
2  * Copyright (c) 2016 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 /*
16   Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus
17
18   Permission is hereby granted, free of charge, to any person obtaining
19   a copy of this software and associated documentation files (the
20   "Software"), to deal in the Software without restriction, including
21   without limitation the rights to use, copy, modify, merge, publish,
22   distribute, sublicense, and/or sell copies of the Software, and to
23   permit persons to whom the Software is furnished to do so, subject to
24   the following conditions:
25
26   The above copyright notice and this permission notice shall be
27   included in all copies or substantial portions of the Software.
28
29   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33   LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 */
37
38 /** \file
39
40     Optimized string handling code, including c11-compliant
41     "safe C library" variants.
42 */
43
44 #ifndef included_clib_string_h
45 #define included_clib_string_h
46
47 #include <vppinfra/clib.h>      /* for CLIB_LINUX_KERNEL */
48 #include <vppinfra/vector.h>
49 #include <vppinfra/error_bootstrap.h>
50 #ifdef __SSE4_2__
51 #include <vppinfra/memcpy_x86_64.h>
52 #endif
53
54 #ifdef CLIB_LINUX_KERNEL
55 #include <linux/string.h>
56 #endif
57
58 #ifdef CLIB_UNIX
59 #include <string.h>
60 #endif
61
62 #ifdef CLIB_STANDALONE
63 #include <vppinfra/standalone_string.h>
64 #endif
65
66 #if _x86_64_
67 #include <x86intrin.h>
68 #endif
69
70 /* Exchanges source and destination. */
71 void clib_memswap (void *_a, void *_b, uword bytes);
72
73
74 static_always_inline void *
75 clib_memcpy_fast (void *restrict dst, const void *restrict src, size_t n)
76 {
77   ASSERT (dst && src &&
78           "memcpy(src, dst, n) with src == NULL or dst == NULL is undefined "
79           "behaviour");
80 #if defined(__COVERITY__)
81   return memcpy (dst, src, n);
82 #elif defined(__SSE4_2__)
83   clib_memcpy_x86_64 (dst, src, n);
84   return dst;
85 #else
86   return memcpy (dst, src, n);
87 #endif
88 }
89
90 static_always_inline void *
91 clib_memmove (void *dst, const void *src, size_t n)
92 {
93   u8 *d = (u8 *) dst;
94   u8 *s = (u8 *) src;
95
96   if (s == d)
97     return d;
98
99   if (d > s)
100     for (uword i = n - 1; (i + 1) > 0; i--)
101       d[i] = s[i];
102   else
103     for (uword i = 0; i < n; i++)
104       d[i] = s[i];
105
106   return d;
107 }
108
109 #include <vppinfra/memcpy.h>
110
111 /* c-11 string manipulation variants */
112
113 #ifndef EOK
114 #define EOK 0
115 #endif
116 #ifndef EINVAL
117 #define EINVAL 22
118 #endif
119 #ifndef ESRCH
120 #define ESRCH 3
121 #endif
122 #ifndef EOVERFLOW
123 #define EOVERFLOW 75
124 #endif
125
126 /*
127  * In order to provide smooth mapping from unsafe string API to the clib string
128  * macro, we often have to improvise s1max and s2max due to the additional
129  * arguments are required for implementing the safe API. This macro is used
130  * to provide the s1max/s2max. It is not perfect because the actual
131  * s1max/s2max may be greater than 4k and the mapping from the unsafe API to
132  * the macro would cause a regression. However, it is not terribly likely.
133  * So I bet against the odds.
134  */
135 #define CLIB_STRING_MACRO_MAX 4096
136
137 typedef int errno_t;
138 typedef uword rsize_t;
139
140 void clib_c11_violation (const char *s);
141 errno_t memcpy_s (void *__restrict__ dest, rsize_t dmax,
142                   const void *__restrict__ src, rsize_t n);
143
144 always_inline errno_t
145 memcpy_s_inline (void *__restrict__ dest, rsize_t dmax,
146                  const void *__restrict__ src, rsize_t n)
147 {
148   uword low, hi;
149   u8 bad;
150
151   /*
152    * Optimize constant-number-of-bytes calls without asking
153    * "too many questions for someone from New Jersey"
154    */
155   if (COMPILE_TIME_CONST (n))
156     {
157       clib_memcpy_fast (dest, src, n);
158       return EOK;
159     }
160
161   /*
162    * call bogus if: src or dst NULL, trying to copy
163    * more data than we have space in dst, or src == dst.
164    * n == 0 isn't really "bad", so check first in the
165    * "wall-of-shame" department...
166    */
167   bad = (dest == 0) + (src == 0) + (n > dmax) + (dest == src) + (n == 0);
168   if (PREDICT_FALSE (bad != 0))
169     {
170       /* Not actually trying to copy anything is OK */
171       if (n == 0)
172         return EOK;
173       if (dest == NULL)
174         clib_c11_violation ("dest NULL");
175       if (src == NULL)
176         clib_c11_violation ("src NULL");
177       if (n > dmax)
178         clib_c11_violation ("n > dmax");
179       if (dest == src)
180         clib_c11_violation ("dest == src");
181       return EINVAL;
182     }
183
184   /* Check for src/dst overlap, which is not allowed */
185   low = (uword) (src < dest ? src : dest);
186   hi = (uword) (src < dest ? dest : src);
187
188   if (PREDICT_FALSE (low + (n - 1) >= hi))
189     {
190       clib_c11_violation ("src/dest overlap");
191       return EINVAL;
192     }
193
194   clib_memcpy_fast (dest, src, n);
195   return EOK;
196 }
197
198 /*
199  * Note: $$$ This macro is a crutch. Folks need to manually
200  * inspect every extant clib_memcpy(...) call and
201  * attempt to provide a real destination buffer size
202  * argument...
203  */
204 #define clib_memcpy(d,s,n) memcpy_s_inline(d,n,s,n)
205
206 errno_t memset_s (void *s, rsize_t smax, int c, rsize_t n);
207
208 always_inline errno_t
209 memset_s_inline (void *s, rsize_t smax, int c, rsize_t n)
210 {
211   u8 bad;
212
213   bad = (s == 0) + (n > smax);
214
215   if (PREDICT_FALSE (bad != 0))
216     {
217       if (s == 0)
218         clib_c11_violation ("s NULL");
219       if (n > smax)
220         clib_c11_violation ("n > smax");
221       return (EINVAL);
222     }
223   memset (s, c, n);
224   return (EOK);
225 }
226
227 /*
228  * This macro is not [so much of] a crutch.
229  * It's super-typical to write:
230  *
231  *   ep = pool_get (<pool>);
232  *   clib_memset(ep, 0, sizeof (*ep));
233  *
234  * The compiler should delete the not-so useful
235  * (n > smax) test. TBH the NULL pointer check isn't
236  * so useful in this case, but so be it.
237  */
238 #define clib_memset(s,c,n) memset_s_inline(s,n,c,n)
239
240 static_always_inline void
241 clib_memcpy_le (u8 * dst, u8 * src, u8 len, u8 max_len)
242 {
243 #if defined (CLIB_HAVE_VEC256)
244   u8x32 s0, s1, d0, d1;
245   u8x32 mask = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
246     18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
247   };
248   u8x32 lv = u8x32_splat (len);
249   u8x32 add = u8x32_splat (32);
250
251   s0 = u8x32_load_unaligned (src);
252   s1 = u8x32_load_unaligned (src + 32);
253   d0 = u8x32_load_unaligned (dst);
254   d1 = u8x32_load_unaligned (dst + 32);
255
256   d0 = u8x32_blend (d0, s0, lv > mask);
257   u8x32_store_unaligned (d0, dst);
258
259   if (max_len <= 32)
260     return;
261
262   mask += add;
263   d1 = u8x32_blend (d1, s1, lv > mask);
264   u8x32_store_unaligned (d1, dst + 32);
265
266 #elif defined (CLIB_HAVE_VEC128)
267   u8x16 s0, s1, s2, s3, d0, d1, d2, d3;
268   u8x16 mask = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
269   u8x16 lv = u8x16_splat (len);
270   u8x16 add = u8x16_splat (16);
271
272   s0 = u8x16_load_unaligned (src);
273   s1 = u8x16_load_unaligned (src + 16);
274   s2 = u8x16_load_unaligned (src + 32);
275   s3 = u8x16_load_unaligned (src + 48);
276   d0 = u8x16_load_unaligned (dst);
277   d1 = u8x16_load_unaligned (dst + 16);
278   d2 = u8x16_load_unaligned (dst + 32);
279   d3 = u8x16_load_unaligned (dst + 48);
280
281   d0 = u8x16_blend (d0, s0, lv > mask);
282   u8x16_store_unaligned (d0, dst);
283
284   if (max_len <= 16)
285     return;
286
287   mask += add;
288   d1 = u8x16_blend (d1, s1, lv > mask);
289   u8x16_store_unaligned (d1, dst + 16);
290
291   if (max_len <= 32)
292     return;
293
294   mask += add;
295   d2 = u8x16_blend (d2, s2, lv > mask);
296   u8x16_store_unaligned (d2, dst + 32);
297
298   mask += add;
299   d3 = u8x16_blend (d3, s3, lv > mask);
300   u8x16_store_unaligned (d3, dst + 48);
301 #else
302   memmove (dst, src, len);
303 #endif
304 }
305
306 static_always_inline void
307 clib_memcpy_le64 (u8 * dst, u8 * src, u8 len)
308 {
309   clib_memcpy_le (dst, src, len, 64);
310 }
311
312 static_always_inline void
313 clib_memcpy_le32 (u8 * dst, u8 * src, u8 len)
314 {
315   clib_memcpy_le (dst, src, len, 32);
316 }
317
318 static_always_inline void
319 clib_memset_u64 (void *p, u64 val, uword count)
320 {
321   u64 *ptr = p;
322 #if defined(CLIB_HAVE_VEC512)
323   u64x8 v512 = u64x8_splat (val);
324   while (count >= 8)
325     {
326       u64x8_store_unaligned (v512, ptr);
327       ptr += 8;
328       count -= 8;
329     }
330   if (count == 0)
331     return;
332 #endif
333 #if defined(CLIB_HAVE_VEC256)
334   u64x4 v256 = u64x4_splat (val);
335   while (count >= 4)
336     {
337       u64x4_store_unaligned (v256, ptr);
338       ptr += 4;
339       count -= 4;
340     }
341   if (count == 0)
342     return;
343 #else
344 #if defined(CLIB_HAVE_VEC128)
345   u64x2 v = u64x2_splat (val);
346 #endif
347   while (count >= 4)
348     {
349 #if defined(CLIB_HAVE_VEC128)
350       u64x2_store_unaligned (v, ptr);
351       u64x2_store_unaligned (v, ptr + 2);
352 #else
353       ptr[0] = ptr[1] = ptr[2] = ptr[3] = val;
354 #endif
355       ptr += 4;
356       count -= 4;
357     }
358 #endif
359   while (count--)
360     ptr++[0] = val;
361 }
362
363 static_always_inline void
364 clib_memset_u32 (void *p, u32 val, uword count)
365 {
366   u32 *ptr = p;
367 #if defined(CLIB_HAVE_VEC512)
368   u32x16 v512 = u32x16_splat (val);
369   while (count >= 16)
370     {
371       u32x16_store_unaligned (v512, ptr);
372       ptr += 16;
373       count -= 16;
374     }
375   if (count == 0)
376     return;
377 #endif
378 #if defined(CLIB_HAVE_VEC256)
379   u32x8 v256 = u32x8_splat (val);
380   while (count >= 8)
381     {
382       u32x8_store_unaligned (v256, ptr);
383       ptr += 8;
384       count -= 8;
385     }
386   if (count == 0)
387     return;
388 #endif
389 #if defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_UNALIGNED_LOAD_STORE)
390   u32x4 v128 = u32x4_splat (val);
391   while (count >= 4)
392     {
393       u32x4_store_unaligned (v128, ptr);
394       ptr += 4;
395       count -= 4;
396     }
397 #else
398   while (count >= 4)
399     {
400       ptr[0] = ptr[1] = ptr[2] = ptr[3] = val;
401       ptr += 4;
402       count -= 4;
403     }
404 #endif
405   while (count--)
406     ptr++[0] = val;
407 }
408
409 static_always_inline void
410 clib_memset_u16 (void *p, u16 val, uword count)
411 {
412   u16 *ptr = p;
413 #if defined(CLIB_HAVE_VEC512)
414   u16x32 v512 = u16x32_splat (val);
415   while (count >= 32)
416     {
417       u16x32_store_unaligned (v512, ptr);
418       ptr += 32;
419       count -= 32;
420     }
421   if (count == 0)
422     return;
423 #endif
424 #if defined(CLIB_HAVE_VEC256)
425   u16x16 v256 = u16x16_splat (val);
426   while (count >= 16)
427     {
428       u16x16_store_unaligned (v256, ptr);
429       ptr += 16;
430       count -= 16;
431     }
432   if (count == 0)
433     return;
434 #endif
435 #if defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_UNALIGNED_LOAD_STORE)
436   u16x8 v128 = u16x8_splat (val);
437   while (count >= 8)
438     {
439       u16x8_store_unaligned (v128, ptr);
440       ptr += 8;
441       count -= 8;
442     }
443 #else
444   while (count >= 4)
445     {
446       ptr[0] = ptr[1] = ptr[2] = ptr[3] = val;
447       ptr += 4;
448       count -= 4;
449     }
450 #endif
451   while (count--)
452     ptr++[0] = val;
453 }
454
455 static_always_inline void
456 clib_memset_u8 (void *p, u8 val, uword count)
457 {
458   u8 *ptr = p;
459 #if defined(CLIB_HAVE_VEC512)
460   u8x64 v512 = u8x64_splat (val);
461   while (count >= 64)
462     {
463       u8x64_store_unaligned (v512, ptr);
464       ptr += 64;
465       count -= 64;
466     }
467   if (count == 0)
468     return;
469 #endif
470 #if defined(CLIB_HAVE_VEC256)
471   u8x32 v256 = u8x32_splat (val);
472   while (count >= 32)
473     {
474       u8x32_store_unaligned (v256, ptr);
475       ptr += 32;
476       count -= 32;
477     }
478   if (count == 0)
479     return;
480 #endif
481 #if defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_UNALIGNED_LOAD_STORE)
482   u8x16 v128 = u8x16_splat (val);
483   while (count >= 16)
484     {
485       u8x16_store_unaligned (v128, ptr);
486       ptr += 16;
487       count -= 16;
488     }
489 #else
490   while (count >= 4)
491     {
492       ptr[0] = ptr[1] = ptr[2] = ptr[3] = val;
493       ptr += 4;
494       count -= 4;
495     }
496 #endif
497   while (count--)
498     ptr++[0] = val;
499 }
500
501
502 /*
503  * This macro is to provide smooth mapping from memcmp to memcmp_s.
504  * memcmp has fewer parameters and fewer returns than memcmp_s.
505  * This macro is somewhat a crutch. When err != EOK is returned from memcmp_s,
506  * we return 0 and spit out a message in the console because there is
507  * no way to return the error code to the memcmp callers.
508  * This condition happens when s1 or s2 is null. Please note
509  * in the extant memcmp calls, if s1, s2, or both are null, memcmp returns 0
510  * anyway. So we are consistent in this case for the comparison return
511  * although we also spit out a C11 violation message in the console to
512  * warn that they pass null pointers for both s1 and s2.
513  * Applications are encouraged to use the cool C11 memcmp_s API to get the
514  * maximum benefit out of it.
515  */
516 #define clib_memcmp(s1,s2,m1) \
517   ({ int __diff = 0;                                   \
518     memcmp_s_inline (s1, m1, s2, m1, &__diff);  \
519     __diff; \
520   })
521
522 errno_t memcmp_s (const void *s1, rsize_t s1max, const void *s2,
523                   rsize_t s2max, int *diff);
524
525 always_inline errno_t
526 memcmp_s_inline (const void *s1, rsize_t s1max, const void *s2, rsize_t s2max,
527                  int *diff)
528 {
529   u8 bad;
530
531   bad = (s1 == 0) + (s2 == 0) + (diff == 0) + (s2max > s1max) + (s2max == 0) +
532     (s1max == 0);
533
534   if (PREDICT_FALSE (bad != 0))
535     {
536       if (s1 == NULL)
537         clib_c11_violation ("s1 NULL");
538       if (s2 == NULL)
539         clib_c11_violation ("s2 NULL");
540       if (diff == NULL)
541         clib_c11_violation ("diff NULL");
542       if (s2max > s1max)
543         clib_c11_violation ("s2max > s1max");
544       if (s2max == 0)
545         clib_c11_violation ("s2max 0");
546       if (s1max == 0)
547         clib_c11_violation ("s1max 0");
548       return EINVAL;
549     }
550
551   if (PREDICT_FALSE (s1 == s2))
552     {
553       *diff = 0;
554       return EOK;
555     }
556
557   *diff = memcmp (s1, s2, s2max);
558   return EOK;
559 }
560
561 /*
562  * This macro is to provide smooth mapping from strnlen to strnlen_s
563  */
564 #define clib_strnlen(s,m) strnlen_s_inline(s,m)
565
566 size_t strnlen_s (const char *s, size_t maxsize);
567
568 always_inline size_t
569 strnlen_s_inline (const char *s, size_t maxsize)
570 {
571   u8 bad;
572
573   bad = (s == 0) + (maxsize == 0);
574   if (PREDICT_FALSE (bad != 0))
575     {
576       if (s == 0)
577         clib_c11_violation ("s NULL");
578       if (maxsize == 0)
579         clib_c11_violation ("maxsize 0");
580       return 0;
581     }
582   return strnlen (s, maxsize);
583 }
584
585 /*
586  * This macro is to provide smooth mapping from strcmp to strcmp_s.
587  * strcmp has fewer parameters and fewer returns than strcmp_s.
588  * This macro is somewhat a crutch. When err != EOK is returned from strcmp_s,
589  * we return 0 and spit out a message in the console because
590  * there is no way to return the error to the strcmp callers.
591  * This condition happens when s1 or s2 is null. Please note in the extant
592  * strcmp call, they would end up crashing if one of them is null.
593  * So the new behavior is no crash, but an error is displayed in the
594  * console which I think is more user friendly. If both s1 and s2 are null,
595  * strcmp returns 0. Obviously, strcmp did the pointers comparison prior
596  * to actually accessing the pointer contents. We are still consistent
597  * in this case for the comparison return although we also spit out a
598  * C11 violation message in the console to warn that they pass null pointers
599  * for both s1 and s2. The other problem is strcmp does not provide s1max,
600  * we use CLIB_STRING_MACRO_MAX and hopefully, s1 is null terminated.
601  * If not, we may be accessing memory beyonf what is intended.
602  * Applications are encouraged to use the cool C11 strcmp_s API to get the
603  * maximum benefit out of it.
604  */
605 #define clib_strcmp(s1,s2) \
606   ({ int __indicator = 0; \
607     strcmp_s_inline (s1, CLIB_STRING_MACRO_MAX, s2, &__indicator);      \
608     __indicator;                        \
609   })
610
611 errno_t strcmp_s (const char *s1, rsize_t s1max, const char *s2,
612                   int *indicator);
613
614 always_inline errno_t
615 strcmp_s_inline (const char *s1, rsize_t s1max, const char *s2,
616                  int *indicator)
617 {
618   u8 bad;
619
620   bad = (indicator == 0) + (s1 == 0) + (s2 == 0) + (s1max == 0) +
621     (s1 && s1max && s1[clib_strnlen (s1, s1max)] != '\0');
622
623   if (PREDICT_FALSE (bad != 0))
624     {
625       if (indicator == NULL)
626         clib_c11_violation ("indicator NULL");
627       if (s1 == NULL)
628         clib_c11_violation ("s1 NULL");
629       if (s2 == NULL)
630         clib_c11_violation ("s2 NULL");
631       if (s1max == 0)
632         clib_c11_violation ("s1max 0");
633       if (s1 && s1max && s1[clib_strnlen (s1, s1max)] != '\0')
634         clib_c11_violation ("s1 unterminated");
635       return EINVAL;
636     }
637
638   *indicator = strcmp (s1, s2);
639   return EOK;
640 }
641
642 /*
643  * This macro is to provide smooth mapping from strncmp to strncmp_s.
644  * strncmp has fewer parameters and fewer returns than strncmp_s. That said,
645  * this macro is somewhat a crutch. When we get err != EOK from strncmp_s,
646  * we return 0 and spit out a message in the console because there is no
647  * means to return the error to the strncmp caller.
648  * This condition happens when s1 or s2 is null. In the extant strncmp call,
649  * they would end up crashing if one of them is null. So the new behavior is
650  * no crash, but error is displayed in the console which is more
651  * user friendly. If s1 and s2 are null, strncmp returns 0. Obviously,
652  * strncmp did the pointers comparison prior to actually accessing the
653  * pointer contents. We are still consistent in this case for the comparison
654  * return although we also spit out a C11 violation message in the console to
655  * warn that they pass null pointers for both s1 and s2.
656  * Applications are encouraged to use the cool C11 strncmp_s API to get the
657  * maximum benefit out of it.
658  */
659 #define clib_strncmp(s1,s2,n) \
660   ({ int __indicator = 0; \
661     strncmp_s_inline (s1, CLIB_STRING_MACRO_MAX, s2, n, &__indicator);  \
662     __indicator;                        \
663   })
664
665 errno_t strncmp_s (const char *s1, rsize_t s1max, const char *s2, rsize_t n,
666                    int *indicator);
667
668 always_inline errno_t
669 strncmp_s_inline (const char *s1, rsize_t s1max, const char *s2, rsize_t n,
670                   int *indicator)
671 {
672   u8 bad;
673   u8 s1_greater_s1max = (s1 && s1max && n > clib_strnlen (s1, s1max));
674
675   if (PREDICT_FALSE (s1_greater_s1max && indicator))
676     {
677       /*
678        * strcmp allows n > s1max. If indicator is non null, we can still
679        * do the compare without any harm and return EINVAL as well as the
680        * result in indicator.
681        */
682       clib_c11_violation ("n exceeds s1 length");
683       *indicator = strncmp (s1, s2, n);
684       return EINVAL;
685     }
686
687   bad = (s1 == 0) + (s2 == 0) + (indicator == 0) + (s1max == 0) +
688     (s1 && s1max && s1[clib_strnlen (s1, s1max)] != '\0') + s1_greater_s1max;
689
690   if (PREDICT_FALSE (bad != 0))
691     {
692       if (indicator == NULL)
693         clib_c11_violation ("indicator NULL");
694       if (s1 == NULL)
695         clib_c11_violation ("s1 NULL");
696       if (s2 == NULL)
697         clib_c11_violation ("s2 NULL");
698       if (s1max == 0)
699         clib_c11_violation ("s1max 0");
700       if (s1 && s1max && s1[clib_strnlen (s1, s1max)] != '\0')
701         clib_c11_violation ("s1 unterminated");
702       if (s1_greater_s1max)
703         clib_c11_violation ("n exceeds s1 length");
704       return EINVAL;
705     }
706
707   *indicator = strncmp (s1, s2, n);
708   return EOK;
709 }
710
711 errno_t strcpy_s (char *__restrict__ dest, rsize_t dmax,
712                   const char *__restrict__ src);
713
714 always_inline errno_t
715 strcpy_s_inline (char *__restrict__ dest, rsize_t dmax,
716                  const char *__restrict__ src)
717 {
718   u8 bad;
719   uword low, hi;
720   size_t n;
721
722   bad = (dest == 0) + (dmax == 0) + (src == 0);
723   if (PREDICT_FALSE (bad != 0))
724     {
725       if (dest == 0)
726         clib_c11_violation ("dest NULL");
727       if (src == 0)
728         clib_c11_violation ("src NULL");
729       if (dmax == 0)
730         clib_c11_violation ("dmax 0");
731       return EINVAL;
732     }
733
734   n = clib_strnlen (src, dmax);
735   if (PREDICT_FALSE (n >= dmax))
736     {
737       clib_c11_violation ("not enough space for dest");
738       return (EINVAL);
739     }
740   /* Not actually trying to copy anything is OK */
741   if (PREDICT_FALSE (n == 0))
742     return EOK;
743
744   /* Check for src/dst overlap, which is not allowed */
745   low = (uword) (src < dest ? src : dest);
746   hi = (uword) (src < dest ? dest : src);
747
748   if (PREDICT_FALSE (low + (n - 1) >= hi))
749     {
750       clib_c11_violation ("src/dest overlap");
751       return EINVAL;
752     }
753
754   clib_memcpy_fast (dest, src, n);
755   dest[n] = '\0';
756   return EOK;
757 }
758
759 /*
760  * This macro is provided for smooth migration from strncpy. It is not perfect
761  * because we don't know the size of the destination buffer to pass to
762  * strncpy_s. We improvise dmax with CLIB_STRING_MACRO_MAX.
763  * Applications are encouraged to move to the C11 strncpy_s API and provide
764  * the correct dmax for better error checking.
765  */
766 #define clib_strncpy(d,s,n) strncpy_s_inline(d,CLIB_STRING_MACRO_MAX,s,n)
767
768 errno_t
769 strncpy_s (char *__restrict__ dest, rsize_t dmax,
770            const char *__restrict__ src, rsize_t n);
771
772 always_inline errno_t
773 strncpy_s_inline (char *__restrict__ dest, rsize_t dmax,
774                   const char *__restrict__ src, rsize_t n)
775 {
776   u8 bad;
777   uword low, hi;
778   rsize_t m;
779   errno_t status = EOK;
780
781   bad = (dest == 0) + (dmax == 0) + (src == 0) + (n == 0);
782   if (PREDICT_FALSE (bad != 0))
783     {
784       /* Not actually trying to copy anything is OK */
785       if (n == 0)
786         return EOK;
787       if (dest == 0)
788         clib_c11_violation ("dest NULL");
789       if (src == 0)
790         clib_c11_violation ("src NULL");
791       if (dmax == 0)
792         clib_c11_violation ("dmax 0");
793       return EINVAL;
794     }
795
796   if (PREDICT_FALSE (n >= dmax))
797     {
798       /* Relax and use strnlen of src */
799       clib_c11_violation ("n >= dmax");
800       m = clib_strnlen (src, dmax);
801       if (m >= dmax)
802         {
803           /* Truncate, adjust copy length to fit dest */
804           m = dmax - 1;
805           status = EOVERFLOW;
806         }
807     }
808   else
809     /* cap the copy to strlen(src) in case n > strlen(src) */
810     m = clib_strnlen (src, n);
811
812   /* Check for src/dst overlap, which is not allowed */
813   low = (uword) (src < dest ? src : dest);
814   hi = (uword) (src < dest ? dest : src);
815
816   /*
817    * This check may fail innocently if src + dmax >= dst, but
818    * src + strlen(src) < dst. If it fails, check more carefully before
819    * blowing the whistle.
820    */
821   if (PREDICT_FALSE (low + (m - 1) >= hi))
822     {
823       m = clib_strnlen (src, m);
824
825       if (low + (m - 1) >= hi)
826         {
827           clib_c11_violation ("src/dest overlap");
828           return EINVAL;
829         }
830     }
831
832   clib_memcpy_fast (dest, src, m);
833   dest[m] = '\0';
834   return status;
835 }
836
837 errno_t strcat_s (char *__restrict__ dest, rsize_t dmax,
838                   const char *__restrict__ src);
839
840 always_inline errno_t
841 strcat_s_inline (char *__restrict__ dest, rsize_t dmax,
842                  const char *__restrict__ src)
843 {
844   u8 bad;
845   uword low, hi;
846   size_t m, n, dest_size;
847
848   bad = (dest == 0) + (dmax == 0) + (src == 0);
849   if (PREDICT_FALSE (bad != 0))
850     {
851       if (dest == 0)
852         clib_c11_violation ("dest NULL");
853       if (src == 0)
854         clib_c11_violation ("src NULL");
855       if (dmax == 0)
856         clib_c11_violation ("dmax 0");
857       return EINVAL;
858     }
859
860   dest_size = clib_strnlen (dest, dmax);
861   m = dmax - dest_size;
862   n = clib_strnlen (src, m);
863   if (PREDICT_FALSE (n >= m))
864     {
865       clib_c11_violation ("not enough space for dest");
866       return EINVAL;
867     }
868
869   /* Not actually trying to concatenate anything is OK */
870   if (PREDICT_FALSE (n == 0))
871     return EOK;
872
873   /* Check for src/dst overlap, which is not allowed */
874   low = (uword) (src < dest ? src : dest);
875   hi = (uword) (src < dest ? dest : src);
876
877   if (PREDICT_FALSE (low + (n - 1) >= hi))
878     {
879       clib_c11_violation ("src/dest overlap");
880       return EINVAL;
881     }
882
883   clib_memcpy_fast (dest + dest_size, src, n);
884   dest[dest_size + n] = '\0';
885   return EOK;
886 }
887
888 errno_t strncat_s (char *__restrict__ dest, rsize_t dmax,
889                    const char *__restrict__ src, rsize_t n);
890
891 always_inline errno_t
892 strncat_s_inline (char *__restrict__ dest, rsize_t dmax,
893                   const char *__restrict__ src, rsize_t n)
894 {
895   u8 bad;
896   uword low, hi;
897   size_t m, dest_size, allowed_size;
898   errno_t status = EOK;
899
900   bad = (dest == 0) + (src == 0) + (dmax == 0) + (n == 0);
901   if (PREDICT_FALSE (bad != 0))
902     {
903       /* Not actually trying to concatenate anything is OK */
904       if (n == 0)
905         return EOK;
906       if (dest == 0)
907         clib_c11_violation ("dest NULL");
908       if (src == 0)
909         clib_c11_violation ("src NULL");
910       if (dmax == 0)
911         clib_c11_violation ("dmax 0");
912       return EINVAL;
913     }
914
915   /* Check for src/dst overlap, which is not allowed */
916   low = (uword) (src < dest ? src : dest);
917   hi = (uword) (src < dest ? dest : src);
918
919   if (PREDICT_FALSE (low + (n - 1) >= hi))
920     {
921       clib_c11_violation ("src/dest overlap");
922       return EINVAL;
923     }
924
925   dest_size = clib_strnlen (dest, dmax);
926   allowed_size = dmax - dest_size;
927
928   if (PREDICT_FALSE (allowed_size == 0))
929     {
930       clib_c11_violation ("no space left in dest");
931       return (EINVAL);
932     }
933
934   if (PREDICT_FALSE (n >= allowed_size))
935     {
936       /*
937        * unlike strcat_s, strncat_s will do the concatenation anyway when
938        * there is not enough space in dest. But it will do the truncation and
939        * null terminate dest
940        */
941       m = clib_strnlen (src, allowed_size);
942       if (m >= allowed_size)
943         {
944           m = allowed_size - 1;
945           status = EOVERFLOW;
946         }
947     }
948   else
949     m = clib_strnlen (src, n);
950
951   clib_memcpy_fast (dest + dest_size, src, m);
952   dest[dest_size + m] = '\0';
953   return status;
954 }
955
956 /*
957  * This macro is to provide smooth mapping from strtok_r to strtok_s.
958  * To map strtok to this macro, the caller would have to supply an additional
959  * argument. strtokr_s requires s1max which the unsafe API does not have. So
960  * we have to improvise it with CLIB_STRING_MACRO_MAX. Unlike strtok_s,
961  * this macro cannot catch unterminated s1 and s2.
962  * Applications are encouraged to use the cool C11 strtok_s API to avoid
963  * these problems.
964  */
965 #define clib_strtok(s1,s2,p)               \
966   ({ rsize_t __s1max = CLIB_STRING_MACRO_MAX;   \
967     strtok_s_inline (s1, &__s1max, s2, p);              \
968   })
969
970 char *strtok_s (char *__restrict__ s1, rsize_t * __restrict__ s1max,
971                 const char *__restrict__ s2, char **__restrict__ ptr);
972
973 always_inline char *
974 strtok_s_inline (char *__restrict__ s1, rsize_t * __restrict__ s1max,
975                  const char *__restrict__ s2, char **__restrict__ ptr)
976 {
977 #define STRTOK_DELIM_MAX_LEN 16
978   u8 bad;
979   const char *pt;
980   char *ptoken;
981   uword dlen, slen;
982
983   bad = (s1max == 0) + (s2 == 0) + (ptr == 0) +
984     ((s1 == 0) && ptr && (*ptr == 0));
985   if (PREDICT_FALSE (bad != 0))
986     {
987       if (s2 == NULL)
988         clib_c11_violation ("s2 NULL");
989       if (s1max == NULL)
990         clib_c11_violation ("s1max is NULL");
991       if (ptr == NULL)
992         clib_c11_violation ("ptr is NULL");
993       /* s1 == 0 and *ptr == null is no good */
994       if ((s1 == 0) && ptr && (*ptr == 0))
995         clib_c11_violation ("s1 and ptr contents are NULL");
996       return 0;
997     }
998
999   if (s1 == 0)
1000     s1 = *ptr;
1001
1002   /*
1003    * scan s1 for a delimiter
1004    */
1005   dlen = *s1max;
1006   ptoken = 0;
1007   while (*s1 != '\0' && !ptoken)
1008     {
1009       if (PREDICT_FALSE (dlen == 0))
1010         {
1011           *ptr = 0;
1012           clib_c11_violation ("s1 unterminated");
1013           return 0;
1014         }
1015
1016       /*
1017        * must scan the entire delimiter list
1018        * ISO should have included a delimiter string limit!!
1019        */
1020       slen = STRTOK_DELIM_MAX_LEN;
1021       pt = s2;
1022       while (*pt != '\0')
1023         {
1024           if (PREDICT_FALSE (slen == 0))
1025             {
1026               *ptr = 0;
1027               clib_c11_violation ("s2 unterminated");
1028               return 0;
1029             }
1030           slen--;
1031           if (*s1 == *pt)
1032             {
1033               ptoken = 0;
1034               break;
1035             }
1036           else
1037             {
1038               pt++;
1039               ptoken = s1;
1040             }
1041         }
1042       s1++;
1043       dlen--;
1044     }
1045
1046   /*
1047    * if the beginning of a token was not found, then no
1048    * need to continue the scan.
1049    */
1050   if (ptoken == 0)
1051     {
1052       *s1max = dlen;
1053       return (ptoken);
1054     }
1055
1056   /*
1057    * Now we need to locate the end of the token
1058    */
1059   while (*s1 != '\0')
1060     {
1061       if (dlen == 0)
1062         {
1063           *ptr = 0;
1064           clib_c11_violation ("s1 unterminated");
1065           return 0;
1066         }
1067
1068       slen = STRTOK_DELIM_MAX_LEN;
1069       pt = s2;
1070       while (*pt != '\0')
1071         {
1072           if (slen == 0)
1073             {
1074               *ptr = 0;
1075               clib_c11_violation ("s2 unterminated");
1076               return 0;
1077             }
1078           slen--;
1079           if (*s1 == *pt)
1080             {
1081               /*
1082                * found a delimiter, set to null
1083                * and return context ptr to next char
1084                */
1085               *s1 = '\0';
1086               *ptr = (s1 + 1);  /* return pointer for next scan */
1087               *s1max = dlen - 1;        /* account for the nulled delimiter */
1088               return (ptoken);
1089             }
1090           else
1091             {
1092               /*
1093                * simply scanning through the delimiter string
1094                */
1095               pt++;
1096             }
1097         }
1098       s1++;
1099       dlen--;
1100     }
1101
1102   *ptr = s1;
1103   *s1max = dlen;
1104   return (ptoken);
1105 }
1106
1107 errno_t strstr_s (char *s1, rsize_t s1max, const char *s2, rsize_t s2max,
1108                   char **substring);
1109
1110 always_inline errno_t
1111 strstr_s_inline (char *s1, rsize_t s1max, const char *s2, rsize_t s2max,
1112                  char **substring)
1113 {
1114   u8 bad;
1115   size_t s1_size, s2_size;
1116
1117   bad =
1118     (s1 == 0) + (s2 == 0) + (substring == 0) + (s1max == 0) + (s2max == 0) +
1119     (s1 && s1max && (s1[clib_strnlen (s1, s1max)] != '\0')) +
1120     (s2 && s2max && (s2[clib_strnlen (s2, s2max)] != '\0'));
1121   if (PREDICT_FALSE (bad != 0))
1122     {
1123       if (s1 == 0)
1124         clib_c11_violation ("s1 NULL");
1125       if (s2 == 0)
1126         clib_c11_violation ("s2 NULL");
1127       if (s1max == 0)
1128         clib_c11_violation ("s1max 0");
1129       if (s2max == 0)
1130         clib_c11_violation ("s2max 0");
1131       if (substring == 0)
1132         clib_c11_violation ("substring NULL");
1133       if (s1 && s1max && (s1[clib_strnlen (s1, s1max)] != '\0'))
1134         clib_c11_violation ("s1 unterminated");
1135       if (s2 && s2max && (s2[clib_strnlen (s2, s2max)] != '\0'))
1136         clib_c11_violation ("s2 unterminated");
1137       return EINVAL;
1138     }
1139
1140   /*
1141    * s2 points to a string with zero length, or s2 equals s1, return s1
1142    */
1143   if (PREDICT_FALSE (*s2 == '\0' || s1 == s2))
1144     {
1145       *substring = s1;
1146       return EOK;
1147     }
1148
1149   /*
1150    * s2_size > s1_size, it won't find match.
1151    */
1152   s1_size = clib_strnlen (s1, s1max);
1153   s2_size = clib_strnlen (s2, s2max);
1154   if (PREDICT_FALSE (s2_size > s1_size))
1155     return ESRCH;
1156
1157   *substring = strstr (s1, s2);
1158   if (*substring == 0)
1159     return ESRCH;
1160
1161   return EOK;
1162 }
1163
1164 static_always_inline const char *
1165 clib_string_skip_prefix (const char *s, const char *prefix)
1166 {
1167   uword len = __builtin_strlen (prefix);
1168   return s + (__builtin_strncmp (s, prefix, len) ? 0 : len);
1169 }
1170
1171 #endif /* included_clib_string_h */
1172
1173 /*
1174  * fd.io coding-style-patch-verification: ON
1175  *
1176  * Local Variables:
1177  * eval: (c-set-style "gnu")
1178  * End:
1179  */