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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus
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:
26 The above copyright notice and this permission notice shall be
27 included in all copies or substantial portions of the Software.
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.
40 Optimized string handling code, including c11-compliant
41 "safe C library" variants.
44 #ifndef included_clib_string_h
45 #define included_clib_string_h
47 #include <vppinfra/clib.h> /* for CLIB_LINUX_KERNEL */
48 #include <vppinfra/vector.h>
50 #ifdef CLIB_LINUX_KERNEL
51 #include <linux/string.h>
58 #ifdef CLIB_STANDALONE
59 #include <vppinfra/standalone_string.h>
63 #include <x86intrin.h>
66 /* Exchanges source and destination. */
67 void clib_memswap (void *_a, void *_b, uword bytes);
70 * the vector unit memcpy variants confuse coverity
71 * so don't let it anywhere near them.
75 #include <vppinfra/memcpy_avx512.h>
77 #include <vppinfra/memcpy_avx2.h>
79 #include <vppinfra/memcpy_sse3.h>
81 #define clib_memcpy_fast(a,b,c) memcpy(a,b,c)
83 #else /* __COVERITY__ */
84 #define clib_memcpy_fast(a,b,c) memcpy(a,b,c)
87 /* c-11 string manipulation variants */
103 * In order to provide smooth mapping from unsafe string API to the clib string
104 * macro, we often have to improvise s1max and s2max due to the additional
105 * arguments are required for implementing the safe API. This macro is used
106 * to provide the s1max/s2max. It is not perfect becuase the actual
107 * s1max/s2max may be greater than 4k and the mapping from the unsafe API to
108 * the macro would cause a regression. However, it is not terribly likely.
109 * So I bet against the odds.
111 #define CLIB_STRING_MACRO_MAX 4096
114 typedef uword rsize_t;
116 void clib_c11_violation (const char *s);
117 errno_t memcpy_s (void *__restrict__ dest, rsize_t dmax,
118 const void *__restrict__ src, rsize_t n);
120 always_inline errno_t
121 memcpy_s_inline (void *__restrict__ dest, rsize_t dmax,
122 const void *__restrict__ src, rsize_t n)
128 * Optimize constant-number-of-bytes calls without asking
129 * "too many questions for someone from New Jersey"
131 if (__builtin_constant_p (n))
133 clib_memcpy_fast (dest, src, n);
138 * call bogus if: src or dst NULL, trying to copy
139 * more data than we have space in dst, or src == dst.
140 * n == 0 isn't really "bad", so check first in the
141 * "wall-of-shame" department...
143 bad = (dest == 0) + (src == 0) + (n > dmax) + (dest == src) + (n == 0);
144 if (PREDICT_FALSE (bad != 0))
146 /* Not actually trying to copy anything is OK */
150 clib_c11_violation ("dest NULL");
152 clib_c11_violation ("src NULL");
154 clib_c11_violation ("n > dmax");
156 clib_c11_violation ("dest == src");
160 /* Check for src/dst overlap, which is not allowed */
161 low = (uword) (src < dest ? src : dest);
162 hi = (uword) (src < dest ? dest : src);
164 if (PREDICT_FALSE (low + (n - 1) >= hi))
166 clib_c11_violation ("src/dest overlap");
170 clib_memcpy_fast (dest, src, n);
175 * Note: $$$ This macro is a crutch. Folks need to manually
176 * inspect every extant clib_memcpy(...) call and
177 * attempt to provide a real destination buffer size
180 #define clib_memcpy(d,s,n) memcpy_s_inline(d,n,s,n)
182 errno_t memset_s (void *s, rsize_t smax, int c, rsize_t n);
184 always_inline errno_t
185 memset_s_inline (void *s, rsize_t smax, int c, rsize_t n)
189 bad = (s == 0) + (n > smax);
191 if (PREDICT_FALSE (bad != 0))
194 clib_c11_violation ("s NULL");
196 clib_c11_violation ("n > smax");
204 * This macro is not [so much of] a crutch.
205 * It's super-typical to write:
207 * ep = pool_get (<pool>);
208 * clib_memset(ep, 0, sizeof (*ep));
210 * The compiler should delete the not-so useful
211 * (n > smax) test. TBH the NULL pointer check isn't
212 * so useful in this case, but so be it.
214 #define clib_memset(s,c,n) memset_s_inline(s,n,c,n)
217 * Copy 64 bytes of data to 4 destinations
218 * this function is typically used in quad-loop case when whole cacheline
219 * needs to be copied to 4 different places. First it reads whole cacheline
220 * to 1/2/4 SIMD registers and then it writes data to 4 destinations.
223 static_always_inline void
224 clib_memcpy64_x4 (void *d0, void *d1, void *d2, void *d3, void *s)
226 #if defined (__AVX512F__)
227 __m512i r0 = _mm512_loadu_si512 (s);
229 _mm512_storeu_si512 (d0, r0);
230 _mm512_storeu_si512 (d1, r0);
231 _mm512_storeu_si512 (d2, r0);
232 _mm512_storeu_si512 (d3, r0);
234 #elif defined (__AVX2__)
235 __m256i r0 = _mm256_loadu_si256 ((__m256i *) (s + 0 * 32));
236 __m256i r1 = _mm256_loadu_si256 ((__m256i *) (s + 1 * 32));
238 _mm256_storeu_si256 ((__m256i *) (d0 + 0 * 32), r0);
239 _mm256_storeu_si256 ((__m256i *) (d0 + 1 * 32), r1);
241 _mm256_storeu_si256 ((__m256i *) (d1 + 0 * 32), r0);
242 _mm256_storeu_si256 ((__m256i *) (d1 + 1 * 32), r1);
244 _mm256_storeu_si256 ((__m256i *) (d2 + 0 * 32), r0);
245 _mm256_storeu_si256 ((__m256i *) (d2 + 1 * 32), r1);
247 _mm256_storeu_si256 ((__m256i *) (d3 + 0 * 32), r0);
248 _mm256_storeu_si256 ((__m256i *) (d3 + 1 * 32), r1);
250 #elif defined (__SSSE3__)
251 __m128i r0 = _mm_loadu_si128 ((__m128i *) (s + 0 * 16));
252 __m128i r1 = _mm_loadu_si128 ((__m128i *) (s + 1 * 16));
253 __m128i r2 = _mm_loadu_si128 ((__m128i *) (s + 2 * 16));
254 __m128i r3 = _mm_loadu_si128 ((__m128i *) (s + 3 * 16));
256 _mm_storeu_si128 ((__m128i *) (d0 + 0 * 16), r0);
257 _mm_storeu_si128 ((__m128i *) (d0 + 1 * 16), r1);
258 _mm_storeu_si128 ((__m128i *) (d0 + 2 * 16), r2);
259 _mm_storeu_si128 ((__m128i *) (d0 + 3 * 16), r3);
261 _mm_storeu_si128 ((__m128i *) (d1 + 0 * 16), r0);
262 _mm_storeu_si128 ((__m128i *) (d1 + 1 * 16), r1);
263 _mm_storeu_si128 ((__m128i *) (d1 + 2 * 16), r2);
264 _mm_storeu_si128 ((__m128i *) (d1 + 3 * 16), r3);
266 _mm_storeu_si128 ((__m128i *) (d2 + 0 * 16), r0);
267 _mm_storeu_si128 ((__m128i *) (d2 + 1 * 16), r1);
268 _mm_storeu_si128 ((__m128i *) (d2 + 2 * 16), r2);
269 _mm_storeu_si128 ((__m128i *) (d2 + 3 * 16), r3);
271 _mm_storeu_si128 ((__m128i *) (d3 + 0 * 16), r0);
272 _mm_storeu_si128 ((__m128i *) (d3 + 1 * 16), r1);
273 _mm_storeu_si128 ((__m128i *) (d3 + 2 * 16), r2);
274 _mm_storeu_si128 ((__m128i *) (d3 + 3 * 16), r3);
277 clib_memcpy_fast (d0, s, 64);
278 clib_memcpy_fast (d1, s, 64);
279 clib_memcpy_fast (d2, s, 64);
280 clib_memcpy_fast (d3, s, 64);
284 static_always_inline void
285 clib_memset_u64 (void *p, u64 val, uword count)
288 #if defined(CLIB_HAVE_VEC512)
289 u64x8 v512 = u64x8_splat (val);
292 u64x8_store_unaligned (v512, ptr);
299 #if defined(CLIB_HAVE_VEC256)
300 u64x4 v256 = u64x4_splat (val);
303 u64x4_store_unaligned (v256, ptr);
312 ptr[0] = ptr[1] = ptr[2] = ptr[3] = val;
321 static_always_inline void
322 clib_memset_u32 (void *p, u32 val, uword count)
325 #if defined(CLIB_HAVE_VEC512)
326 u32x16 v512 = u32x16_splat (val);
329 u32x16_store_unaligned (v512, ptr);
336 #if defined(CLIB_HAVE_VEC256)
337 u32x8 v256 = u32x8_splat (val);
340 u32x8_store_unaligned (v256, ptr);
347 #if defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_UNALIGNED_LOAD_STORE)
348 u32x4 v128 = u32x4_splat (val);
351 u32x4_store_unaligned (v128, ptr);
358 ptr[0] = ptr[1] = ptr[2] = ptr[3] = val;
367 static_always_inline void
368 clib_memset_u16 (void *p, u16 val, uword count)
371 #if defined(CLIB_HAVE_VEC512)
372 u16x32 v512 = u16x32_splat (val);
375 u16x32_store_unaligned (v512, ptr);
382 #if defined(CLIB_HAVE_VEC256)
383 u16x16 v256 = u16x16_splat (val);
386 u16x16_store_unaligned (v256, ptr);
393 #if defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_UNALIGNED_LOAD_STORE)
394 u16x8 v128 = u16x8_splat (val);
397 u16x8_store_unaligned (v128, ptr);
404 ptr[0] = ptr[1] = ptr[2] = ptr[3] = val;
413 static_always_inline void
414 clib_memset_u8 (void *p, u8 val, uword count)
417 #if defined(CLIB_HAVE_VEC512)
418 u8x64 v512 = u8x64_splat (val);
421 u8x64_store_unaligned (v512, ptr);
428 #if defined(CLIB_HAVE_VEC256)
429 u8x32 v256 = u8x32_splat (val);
432 u8x32_store_unaligned (v256, ptr);
439 #if defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_UNALIGNED_LOAD_STORE)
440 u8x16 v128 = u8x16_splat (val);
443 u8x16_store_unaligned (v128, ptr);
450 ptr[0] = ptr[1] = ptr[2] = ptr[3] = val;
459 static_always_inline uword
460 clib_count_equal_u64 (u64 * data, uword max_count)
467 if (data[0] != data[1])
473 #if defined(CLIB_HAVE_VEC256)
474 u64x4 splat = u64x4_splat (first);
478 bmp = u8x32_msb_mask ((u8x32) (u64x4_load_unaligned (data) == splat));
479 if (bmp != 0xffffffff)
481 count += count_trailing_zeros (~bmp) / 8;
482 return clib_min (count, max_count);
488 if (count >= max_count)
494 while (count + 3 < max_count &&
495 ((data[0] ^ first) | (data[1] ^ first) |
496 (data[2] ^ first) | (data[3] ^ first)) == 0)
501 while (count < max_count && (data[0] == first))
509 static_always_inline uword
510 clib_count_equal_u32 (u32 * data, uword max_count)
517 if (data[0] != data[1])
523 #if defined(CLIB_HAVE_VEC256)
524 u32x8 splat = u32x8_splat (first);
528 bmp = u8x32_msb_mask ((u8x32) (u32x8_load_unaligned (data) == splat));
529 if (bmp != 0xffffffff)
531 count += count_trailing_zeros (~bmp) / 4;
532 return clib_min (count, max_count);
538 if (count >= max_count)
541 #elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_MSB_MASK)
542 u32x4 splat = u32x4_splat (first);
546 bmp = u8x16_msb_mask ((u8x16) (u32x4_load_unaligned (data) == splat));
549 count += count_trailing_zeros (~bmp) / 4;
550 return clib_min (count, max_count);
556 if (count >= max_count)
562 while (count + 3 < max_count &&
563 ((data[0] ^ first) | (data[1] ^ first) |
564 (data[2] ^ first) | (data[3] ^ first)) == 0)
569 while (count < max_count && (data[0] == first))
577 static_always_inline uword
578 clib_count_equal_u16 (u16 * data, uword max_count)
585 if (data[0] != data[1])
591 #if defined(CLIB_HAVE_VEC256)
592 u16x16 splat = u16x16_splat (first);
596 bmp = u8x32_msb_mask ((u8x32) (u16x16_load_unaligned (data) == splat));
597 if (bmp != 0xffffffff)
599 count += count_trailing_zeros (~bmp) / 2;
600 return clib_min (count, max_count);
606 if (count >= max_count)
609 #elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_MSB_MASK)
610 u16x8 splat = u16x8_splat (first);
614 bmp = u8x16_msb_mask ((u8x16) (u16x8_load_unaligned (data) == splat));
617 count += count_trailing_zeros (~bmp) / 2;
618 return clib_min (count, max_count);
624 if (count >= max_count)
630 while (count + 3 < max_count &&
631 ((data[0] ^ first) | (data[1] ^ first) |
632 (data[2] ^ first) | (data[3] ^ first)) == 0)
637 while (count < max_count && (data[0] == first))
645 static_always_inline uword
646 clib_count_equal_u8 (u8 * data, uword max_count)
653 if (data[0] != data[1])
659 #if defined(CLIB_HAVE_VEC256)
660 u8x32 splat = u8x32_splat (first);
664 bmp = u8x32_msb_mask ((u8x32) (u8x32_load_unaligned (data) == splat));
665 if (bmp != 0xffffffff)
667 count += count_trailing_zeros (~bmp);
668 return clib_min (count, max_count);
674 if (count >= max_count)
677 #elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_MSB_MASK)
678 u8x16 splat = u8x16_splat (first);
682 bmp = u8x16_msb_mask ((u8x16) (u8x16_load_unaligned (data) == splat));
685 count += count_trailing_zeros (~bmp);
686 return clib_min (count, max_count);
692 if (count >= max_count)
698 while (count + 3 < max_count &&
699 ((data[0] ^ first) | (data[1] ^ first) |
700 (data[2] ^ first) | (data[3] ^ first)) == 0)
705 while (count < max_count && (data[0] == first))
714 * This macro is to provide smooth mapping from memcmp to memcmp_s.
715 * memcmp has fewer parameters and fewer returns than memcmp_s.
716 * This macro is somewhat a crutch. When err != EOK is returned from memcmp_s,
717 * we return 0 and spit out a message in the console because there is
718 * no way to return the error code to the memcmp callers.
719 * This condition happens when s1 or s2 is null. Please note
720 * in the extant memcmp calls, if s1, s2, or both are null, memcmp returns 0
721 * anyway. So we are consistent in this case for the comparison return
722 * although we also spit out a C11 violation message in the console to
723 * warn that they pass null pointers for both s1 and s2.
724 * Applications are encouraged to use the cool C11 memcmp_s API to get the
725 * maximum benefit out of it.
727 #define clib_memcmp(s1,s2,m1) \
729 memcmp_s_inline (s1, m1, s2, m1, &__diff); \
733 errno_t memcmp_s (const void *s1, rsize_t s1max, const void *s2,
734 rsize_t s2max, int *diff);
736 always_inline errno_t
737 memcmp_s_inline (const void *s1, rsize_t s1max, const void *s2, rsize_t s2max,
742 bad = (s1 == 0) + (s2 == 0) + (diff == 0) + (s2max > s1max) + (s2max == 0) +
745 if (PREDICT_FALSE (bad != 0))
748 clib_c11_violation ("s1 NULL");
750 clib_c11_violation ("s2 NULL");
752 clib_c11_violation ("diff NULL");
754 clib_c11_violation ("s2max > s1max");
756 clib_c11_violation ("s2max 0");
758 clib_c11_violation ("s1max 0");
762 if (PREDICT_FALSE (s1 == s2))
768 *diff = memcmp (s1, s2, s2max);
773 * This macro is to provide smooth mapping from strnlen to strnlen_s
775 #define clib_strnlen(s,m) strnlen_s_inline(s,m)
777 size_t strnlen_s (const char *s, size_t maxsize);
780 strnlen_s_inline (const char *s, size_t maxsize)
784 bad = (s == 0) + (maxsize == 0);
785 if (PREDICT_FALSE (bad != 0))
788 clib_c11_violation ("s NULL");
790 clib_c11_violation ("maxsize 0");
793 return strnlen (s, maxsize);
797 * This macro is to provide smooth mapping from strcmp to strcmp_s.
798 * strcmp has fewer parameters and fewer returns than strcmp_s.
799 * This macro is somewhat a crutch. When err != EOK is returned from strcmp_s,
800 * we return 0 and spit out a message in the console because
801 * there is no way to return the error to the strcmp callers.
802 * This condition happens when s1 or s2 is null. Please note in the extant
803 * strcmp call, they would end up crashing if one of them is null.
804 * So the new behavior is no crash, but an error is displayed in the
805 * console which I think is more user friendly. If both s1 and s2 are null,
806 * strcmp returns 0. Obviously, strcmp did the pointers comparison prior
807 * to actually accessing the pointer contents. We are still consistent
808 * in this case for the comparison return although we also spit out a
809 * C11 violation message in the console to warn that they pass null pointers
810 * for both s1 and s2. The other problem is strcmp does not provide s1max,
811 * we use CLIB_STRING_MACRO_MAX and hopefully, s1 is null terminated.
812 * If not, we may be accessing memory beyonf what is intended.
813 * Applications are encouraged to use the cool C11 strcmp_s API to get the
814 * maximum benefit out of it.
816 #define clib_strcmp(s1,s2) \
817 ({ int __indicator = 0; \
818 strcmp_s_inline (s1, CLIB_STRING_MACRO_MAX, s2, &__indicator); \
822 errno_t strcmp_s (const char *s1, rsize_t s1max, const char *s2,
825 always_inline errno_t
826 strcmp_s_inline (const char *s1, rsize_t s1max, const char *s2,
831 bad = (indicator == 0) + (s1 == 0) + (s2 == 0) + (s1max == 0) +
832 (s1 && s1max && s1[clib_strnlen (s1, s1max)] != '\0');
834 if (PREDICT_FALSE (bad != 0))
836 if (indicator == NULL)
837 clib_c11_violation ("indicator NULL");
839 clib_c11_violation ("s1 NULL");
841 clib_c11_violation ("s2 NULL");
843 clib_c11_violation ("s1max 0");
844 if (s1 && s1max && s1[clib_strnlen (s1, s1max)] != '\0')
845 clib_c11_violation ("s1 unterminated");
849 *indicator = strcmp (s1, s2);
854 * This macro is to provide smooth mapping from strncmp to strncmp_s.
855 * strncmp has fewer parameters and fewer returns than strncmp_s. That said,
856 * this macro is somewhat a crutch. When we get err != EOK from strncmp_s,
857 * we return 0 and spit out a message in the console because there is no
858 * means to return the error to the strncmp caller.
859 * This condition happens when s1 or s2 is null. In the extant strncmp call,
860 * they would end up crashing if one of them is null. So the new behavior is
861 * no crash, but error is displayed in the console which is more
862 * user friendly. If s1 and s2 are null, strncmp returns 0. Obviously,
863 * strncmp did the pointers comparison prior to actually accessing the
864 * pointer contents. We are still consistent in this case for the comparison
865 * return although we also spit out a C11 violation message in the console to
866 * warn that they pass null pointers for both s1 and s2.
867 * Applications are encouraged to use the cool C11 strncmp_s API to get the
868 * maximum benefit out of it.
870 #define clib_strncmp(s1,s2,n) \
871 ({ int __indicator = 0; \
872 strncmp_s_inline (s1, CLIB_STRING_MACRO_MAX, s2, n, &__indicator); \
876 errno_t strncmp_s (const char *s1, rsize_t s1max, const char *s2, rsize_t n,
879 always_inline errno_t
880 strncmp_s_inline (const char *s1, rsize_t s1max, const char *s2, rsize_t n,
884 u8 s1_greater_s1max = (s1 && s1max && n > clib_strnlen (s1, s1max));
886 if (PREDICT_FALSE (s1_greater_s1max && indicator))
889 * strcmp allows n > s1max. If indicator is non null, we can still
890 * do the compare without any harm and return EINVAL as well as the
891 * result in indicator.
893 clib_c11_violation ("n exceeds s1 length");
894 *indicator = strncmp (s1, s2, n);
898 bad = (s1 == 0) + (s2 == 0) + (indicator == 0) + (s1max == 0) +
899 (s1 && s1max && s1[clib_strnlen (s1, s1max)] != '\0') + s1_greater_s1max;
901 if (PREDICT_FALSE (bad != 0))
903 if (indicator == NULL)
904 clib_c11_violation ("indicator NULL");
906 clib_c11_violation ("s1 NULL");
908 clib_c11_violation ("s2 NULL");
910 clib_c11_violation ("s1max 0");
911 if (s1 && s1max && s1[clib_strnlen (s1, s1max)] != '\0')
912 clib_c11_violation ("s1 unterminated");
913 if (s1_greater_s1max)
914 clib_c11_violation ("n exceeds s1 length");
918 *indicator = strncmp (s1, s2, n);
923 * This macro is provided for smooth migration from strcpy. It is not perfect
924 * because we don't know the size of the destination buffer to pass to strcpy_s.
925 * We improvise dmax with CLIB_STRING_MACRO_MAX.
926 * Applications are encouraged to move to the C11 strcpy_s API.
928 #define clib_strcpy(d,s) strcpy_s_inline(d,CLIB_STRING_MACRO_MAX,s)
930 errno_t strcpy_s (char *__restrict__ dest, rsize_t dmax,
931 const char *__restrict__ src);
933 always_inline errno_t
934 strcpy_s_inline (char *__restrict__ dest, rsize_t dmax,
935 const char *__restrict__ src)
941 bad = (dest == 0) + (dmax == 0) + (src == 0);
942 if (PREDICT_FALSE (bad != 0))
945 clib_c11_violation ("dest NULL");
947 clib_c11_violation ("src NULL");
949 clib_c11_violation ("dmax 0");
953 n = clib_strnlen (src, dmax);
954 if (PREDICT_FALSE (n >= dmax))
956 clib_c11_violation ("not enough space for dest");
959 /* Not actually trying to copy anything is OK */
960 if (PREDICT_FALSE (n == 0))
963 /* Check for src/dst overlap, which is not allowed */
964 low = (uword) (src < dest ? src : dest);
965 hi = (uword) (src < dest ? dest : src);
967 if (PREDICT_FALSE (low + (n - 1) >= hi))
969 clib_c11_violation ("src/dest overlap");
973 clib_memcpy_fast (dest, src, n);
979 * This macro is provided for smooth migration from strncpy. It is not perfect
980 * because we don't know the size of the destination buffer to pass to
981 * strncpy_s. We improvise dmax with CLIB_STRING_MACRO_MAX.
982 * Applications are encouraged to move to the C11 strncpy_s API and provide
983 * the correct dmax for better error checking.
985 #define clib_strncpy(d,s,n) strncpy_s_inline(d,CLIB_STRING_MACRO_MAX,s,n)
988 strncpy_s (char *__restrict__ dest, rsize_t dmax,
989 const char *__restrict__ src, rsize_t n);
991 always_inline errno_t
992 strncpy_s_inline (char *__restrict__ dest, rsize_t dmax,
993 const char *__restrict__ src, rsize_t n)
998 errno_t status = EOK;
1000 bad = (dest == 0) + (dmax == 0) + (src == 0) + (n == 0);
1001 if (PREDICT_FALSE (bad != 0))
1003 /* Not actually trying to copy anything is OK */
1007 clib_c11_violation ("dest NULL");
1009 clib_c11_violation ("src NULL");
1011 clib_c11_violation ("dmax 0");
1015 if (PREDICT_FALSE (n >= dmax))
1017 /* Relax and use strnlen of src */
1018 clib_c11_violation ("n >= dmax");
1019 m = clib_strnlen (src, dmax);
1022 /* Truncate, adjust copy length to fit dest */
1030 /* Check for src/dst overlap, which is not allowed */
1031 low = (uword) (src < dest ? src : dest);
1032 hi = (uword) (src < dest ? dest : src);
1035 * This check may fail innocently if src + dmax >= dst, but
1036 * src + strlen(src) < dst. If it fails, check more carefully before
1037 * blowing the whistle.
1039 if (PREDICT_FALSE (low + (m - 1) >= hi))
1041 m = clib_strnlen (src, m);
1043 if (low + (m - 1) >= hi)
1045 clib_c11_violation ("src/dest overlap");
1050 clib_memcpy_fast (dest, src, m);
1056 * This macro is to provide smooth migration from strcat to strcat_s.
1057 * Because there is no dmax in strcat, we improvise it with
1058 * CLIB_STRING_MACRO_MAX. Please note there may be a chance to overwrite dest
1059 * with too many bytes from src.
1060 * Applications are encouraged to use C11 API to provide the actual dmax
1061 * for proper checking and protection.
1063 #define clib_strcat(d,s) strcat_s_inline(d,CLIB_STRING_MACRO_MAX,s)
1065 errno_t strcat_s (char *__restrict__ dest, rsize_t dmax,
1066 const char *__restrict__ src);
1068 always_inline errno_t
1069 strcat_s_inline (char *__restrict__ dest, rsize_t dmax,
1070 const char *__restrict__ src)
1074 size_t m, n, dest_size;
1076 bad = (dest == 0) + (dmax == 0) + (src == 0);
1077 if (PREDICT_FALSE (bad != 0))
1080 clib_c11_violation ("dest NULL");
1082 clib_c11_violation ("src NULL");
1084 clib_c11_violation ("dmax 0");
1088 dest_size = clib_strnlen (dest, dmax);
1089 m = dmax - dest_size;
1090 n = clib_strnlen (src, m);
1091 if (PREDICT_FALSE (n >= m))
1093 clib_c11_violation ("not enough space for dest");
1097 /* Not actually trying to concatenate anything is OK */
1098 if (PREDICT_FALSE (n == 0))
1101 /* Check for src/dst overlap, which is not allowed */
1102 low = (uword) (src < dest ? src : dest);
1103 hi = (uword) (src < dest ? dest : src);
1105 if (PREDICT_FALSE (low + (n - 1) >= hi))
1107 clib_c11_violation ("src/dest overlap");
1111 clib_memcpy_fast (dest + dest_size, src, n);
1112 dest[dest_size + n] = '\0';
1117 * This macro is to provide smooth migration from strncat to strncat_s.
1118 * The unsafe strncat does not have s1max. We improvise it with
1119 * CLIB_STRING_MACRO_MAX. Please note there may be a chance to overwrite
1120 * dest with too many bytes from src.
1121 * Applications are encouraged to move to C11 strncat_s which requires dmax
1122 * from the caller and provides checking to safeguard the memory corruption.
1124 #define clib_strncat(d,s,n) strncat_s_inline(d,CLIB_STRING_MACRO_MAX,s,n)
1126 errno_t strncat_s (char *__restrict__ dest, rsize_t dmax,
1127 const char *__restrict__ src, rsize_t n);
1129 always_inline errno_t
1130 strncat_s_inline (char *__restrict__ dest, rsize_t dmax,
1131 const char *__restrict__ src, rsize_t n)
1135 size_t m, dest_size, allowed_size;
1136 errno_t status = EOK;
1138 bad = (dest == 0) + (src == 0) + (dmax == 0) + (n == 0);
1139 if (PREDICT_FALSE (bad != 0))
1141 /* Not actually trying to concatenate anything is OK */
1145 clib_c11_violation ("dest NULL");
1147 clib_c11_violation ("src NULL");
1149 clib_c11_violation ("dmax 0");
1153 /* Check for src/dst overlap, which is not allowed */
1154 low = (uword) (src < dest ? src : dest);
1155 hi = (uword) (src < dest ? dest : src);
1157 if (PREDICT_FALSE (low + (n - 1) >= hi))
1159 clib_c11_violation ("src/dest overlap");
1163 dest_size = clib_strnlen (dest, dmax);
1164 allowed_size = dmax - dest_size;
1166 if (PREDICT_FALSE (allowed_size == 0))
1168 clib_c11_violation ("no space left in dest");
1172 if (PREDICT_FALSE (n >= allowed_size))
1175 * unlike strcat_s, strncat_s will do the concatenation anyway when
1176 * there is not enough space in dest. But it will do the truncation and
1177 * null terminate dest
1179 m = clib_strnlen (src, allowed_size);
1180 if (m >= allowed_size)
1182 m = allowed_size - 1;
1187 m = clib_strnlen (src, n);
1189 clib_memcpy_fast (dest + dest_size, src, m);
1190 dest[dest_size + m] = '\0';
1195 * This macro is to provide smooth mapping from strtok_r to strtok_s.
1196 * To map strtok to this macro, the caller would have to supply an additional
1197 * argument. strtokr_s requires s1max which the unsafe API does not have. So
1198 * we have to improvise it with CLIB_STRING_MACRO_MAX. Unlike strtok_s,
1199 * this macro cannot catch unterminated s1 and s2.
1200 * Applications are encouraged to use the cool C11 strtok_s API to avoid
1203 #define clib_strtok(s1,s2,p) \
1204 ({ rsize_t __s1max = CLIB_STRING_MACRO_MAX; \
1205 strtok_s_inline (s1, &__s1max, s2, p); \
1208 char *strtok_s (char *__restrict__ s1, rsize_t * __restrict__ s1max,
1209 const char *__restrict__ s2, char **__restrict__ ptr);
1211 always_inline char *
1212 strtok_s_inline (char *__restrict__ s1, rsize_t * __restrict__ s1max,
1213 const char *__restrict__ s2, char **__restrict__ ptr)
1215 #define STRTOK_DELIM_MAX_LEN 16
1221 bad = (s1max == 0) + (s2 == 0) + (ptr == 0) +
1222 ((s1 == 0) && ptr && (*ptr == 0));
1223 if (PREDICT_FALSE (bad != 0))
1226 clib_c11_violation ("s2 NULL");
1228 clib_c11_violation ("s1max is NULL");
1230 clib_c11_violation ("ptr is NULL");
1231 /* s1 == 0 and *ptr == null is no good */
1232 if ((s1 == 0) && ptr && (*ptr == 0))
1233 clib_c11_violation ("s1 and ptr contents are NULL");
1241 * scan s1 for a delimiter
1245 while (*s1 != '\0' && !ptoken)
1247 if (PREDICT_FALSE (dlen == 0))
1250 clib_c11_violation ("s1 unterminated");
1255 * must scan the entire delimiter list
1256 * ISO should have included a delimiter string limit!!
1258 slen = STRTOK_DELIM_MAX_LEN;
1262 if (PREDICT_FALSE (slen == 0))
1265 clib_c11_violation ("s2 unterminated");
1285 * if the beginning of a token was not found, then no
1286 * need to continue the scan.
1295 * Now we need to locate the end of the token
1302 clib_c11_violation ("s1 unterminated");
1306 slen = STRTOK_DELIM_MAX_LEN;
1313 clib_c11_violation ("s2 unterminated");
1320 * found a delimiter, set to null
1321 * and return context ptr to next char
1324 *ptr = (s1 + 1); /* return pointer for next scan */
1325 *s1max = dlen - 1; /* account for the nulled delimiter */
1331 * simply scanning through the delimiter string
1346 * This macro is to provide smooth mapping from strstr to strstr_s.
1347 * strstr_s requires s1max and s2max which the unsafe API does not have. So
1348 * we have to improvise them with CLIB_STRING_MACRO_MAX which may cause us
1349 * to access memory beyond it is intended if s1 or s2 is unterminated.
1350 * For the record, strstr crashes if s1 or s2 is unterminated. But this macro
1352 * Applications are encouraged to use the cool C11 strstr_s API to avoid
1355 #define clib_strstr(s1,s2) \
1356 ({ char * __substring = 0; \
1357 strstr_s_inline (s1, CLIB_STRING_MACRO_MAX, s2, CLIB_STRING_MACRO_MAX, \
1362 errno_t strstr_s (char *s1, rsize_t s1max, const char *s2, rsize_t s2max,
1365 always_inline errno_t
1366 strstr_s_inline (char *s1, rsize_t s1max, const char *s2, rsize_t s2max,
1370 size_t s1_size, s2_size;
1373 (s1 == 0) + (s2 == 0) + (substring == 0) + (s1max == 0) + (s2max == 0) +
1374 (s1 && s1max && (s1[clib_strnlen (s1, s1max)] != '\0')) +
1375 (s2 && s2max && (s2[clib_strnlen (s2, s2max)] != '\0'));
1376 if (PREDICT_FALSE (bad != 0))
1379 clib_c11_violation ("s1 NULL");
1381 clib_c11_violation ("s2 NULL");
1383 clib_c11_violation ("s1max 0");
1385 clib_c11_violation ("s2max 0");
1387 clib_c11_violation ("substring NULL");
1388 if (s1 && s1max && (s1[clib_strnlen (s1, s1max)] != '\0'))
1389 clib_c11_violation ("s1 unterminated");
1390 if (s2 && s2max && (s2[clib_strnlen (s2, s1max)] != '\0'))
1391 clib_c11_violation ("s2 unterminated");
1396 * s2 points to a string with zero length, or s2 equals s1, return s1
1398 if (PREDICT_FALSE (*s2 == '\0' || s1 == s2))
1405 * s2_size > s1_size, it won't find match.
1407 s1_size = clib_strnlen (s1, s1max);
1408 s2_size = clib_strnlen (s2, s2max);
1409 if (PREDICT_FALSE (s2_size > s1_size))
1412 *substring = strstr (s1, s2);
1413 if (*substring == 0)
1419 #endif /* included_clib_string_h */
1422 * fd.io coding-style-patch-verification: ON
1425 * eval: (c-set-style "gnu")