Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F132642078
D10469.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
120 KB
Referenced Files
None
Subscribers
None
D10469.diff
View Options
Index: include/string.h
===================================================================
--- include/string.h
+++ include/string.h
@@ -154,8 +154,31 @@
typedef int errno_t;
#endif
-/* ISO/IEC 9899:2011 K.3.7.4.1.1 */
+/* ISO/IEC 9899:2011 K.3.7.1.1 */
+errno_t memcpy_s(void * __restrict, rsize_t, const void * __restrict, rsize_t);
+/* ISO/IEC 9899:2011 K.3.7.1.2 */
+errno_t memmove_s(void *, rsize_t, const void *, rsize_t);
+/* ISO/IEC 9899:2011 K.3.7.1.3 */
+errno_t strcpy_s(char * __restrict, rsize_t, const char * __restrict);
+/* ISO/IEC 9899:2011 K.3.7.1.4 */
+errno_t strncpy_s(char * __restrict, rsize_t, const char * __restrict,
+ rsize_t);
+/* ISO/IEC 9899:2011 K.3.7.2.1 */
+errno_t strcat_s(char * __restrict, rsize_t, const char * __restrict);
+/* ISO/IEC 9899:2011 K.3.7.2.2 */
+errno_t strncat_s(char * __restrict, rsize_t, const char * __restrict,
+ rsize_t);
+/* ISO/IEC 9899:2011 K.3.7.3.1 */
+char *strtok_s(char * __restrict, rsize_t * __restrict,
+ const char * __restrict, char ** __restrict);
+/* ISO/IEC 9899:2011 K.3.7.4.1 */
errno_t memset_s(void *, rsize_t, int, rsize_t);
+/* ISO/IEC 9899:2011 K.3.7.4.2 */
+errno_t strerror_s(char *, rsize_t, errno_t);
+/* ISO/IEC 9899:2011 K.3.7.4.3 */
+size_t strerrorlen_s(errno_t);
+/* ISO/IEC 9899:2011 K.3.7.4.4 */
+size_t strnlen_s(const char *, size_t);
#endif /* __EXT1_VISIBLE */
__END_DECLS
Index: lib/libc/string/Makefile.inc
===================================================================
--- lib/libc/string/Makefile.inc
+++ lib/libc/string/Makefile.inc
@@ -9,17 +9,16 @@
# machine-independent string sources
MISRCS+=bcmp.c bcopy.c bzero.c explicit_bzero.c \
ffs.c ffsl.c ffsll.c fls.c flsl.c flsll.c \
- memccpy.c memchr.c memrchr.c memcmp.c \
- memcpy.c memmem.c memmove.c memset.c memset_s.c \
- stpcpy.c stpncpy.c strcasecmp.c \
- strcat.c strcasestr.c strchr.c strchrnul.c strcmp.c strcoll.c strcpy.c\
- strcspn.c strdup.c strerror.c strlcat.c strlcpy.c strlen.c strmode.c \
- strncat.c strncmp.c strncpy.c strndup.c strnlen.c strnstr.c \
- strpbrk.c strrchr.c strsep.c strsignal.c strspn.c strstr.c strtok.c \
- strxfrm.c swab.c \
- timingsafe_bcmp.c \
- timingsafe_memcmp.c \
- wcpcpy.c wcpncpy.c wcscasecmp.c wcscat.c \
+ memccpy.c memchr.c memrchr.c memcmp.c memcpy.c memcpy_s.c \
+ memmem.c memmove.c memmove_s.c memset.c memset_s.c stpcpy.c \
+ stpncpy.c strcasecmp.c strcat.c strcat_s.c strcasestr.c \
+ strchr.c strchrnul.c strcmp.c strcoll.c strcpy.c strcpy_s.c \
+ strcspn.c strdup.c strerror.c strerror_s.c strerrorlen_s.c \
+ strlcat.c strlcpy.c strlen.c strmode.c strncat.c strncat_s.c \
+ strncmp.c strncpy.c strncpy_s.c strndup.c strnlen.c strnlen_s.c \
+ strnstr.c strpbrk.c strrchr.c strsep.c strsignal.c strspn.c \
+ strstr.c strtok.c strtok_s.c strxfrm.c swab.c timingsafe_bcmp.c \
+ timingsafe_memcmp.c wcpcpy.c wcpncpy.c wcscasecmp.c wcscat.c \
wcschr.c wcscmp.c wcscoll.c wcscpy.c wcscspn.c wcsdup.c \
wcslcat.c wcslcpy.c wcslen.c wcsncasecmp.c wcsncat.c wcsncmp.c \
wcsncpy.c wcsnlen.c wcspbrk.c \
Index: lib/libc/string/Symbol.map
===================================================================
--- lib/libc/string/Symbol.map
+++ lib/libc/string/Symbol.map
@@ -105,7 +105,17 @@
};
FBSD_1.5 {
+ memcpy_s;
+ memmove_s;
memset_s;
+ strcat_s;
+ strcpy_s;
+ strerror_s;
+ strerrorlen_s;
+ strncat_s;
+ strncpy_s;
+ strnlen_s;
+ strtok_s;
timingsafe_bcmp;
timingsafe_memcmp;
};
Index: lib/libc/string/memcpy_s.c
===================================================================
--- /dev/null
+++ lib/libc/string/memcpy_s.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2017 Juniper Networks. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include "libc_private.h"
+
+/* ISO/IEC 9899:2011 K.3.7.1.1 */
+errno_t memcpy_s(void * __restrict s1, rsize_t s1max,
+ const void * __restrict s2, rsize_t n)
+{
+ rsize_t lim;
+ uintptr_t s1e, s2e;
+ errno_t ret;
+ int zero_fill;
+
+ ret = EINVAL;
+ zero_fill = 0;
+
+ if (s1 == NULL) {
+ __throw_constraint_handler_s("memcpy_s : s1 is NULL", ret);
+ } else if (s1max > RSIZE_MAX) {
+ __throw_constraint_handler_s("memcpy_s : s1max > RSIZE_MAX",
+ ret);
+ } else if (s2 == NULL) {
+ zero_fill = 1;
+ __throw_constraint_handler_s("memcpy_s : s2 is NULL", ret);
+ } else if (n > RSIZE_MAX) {
+ zero_fill = 1;
+ __throw_constraint_handler_s("memcpy_s : n > RSIZE_MAX", ret);
+ } else {
+ lim = s1max;
+ if (n < s1max)
+ lim = n;
+ if (lim > 0) {
+ s1e = (uintptr_t) s1 + lim;
+ s2e = (uintptr_t) s2 + lim;
+ if (((uintptr_t) s1 >= (uintptr_t) s2 &&
+ (uintptr_t) s1 < s2e) ||
+ ((uintptr_t) s2 >= (uintptr_t) s1 &&
+ (uintptr_t) s2 < s1e)) {
+ /* do not zero fill on overlap */
+ __throw_constraint_handler_s(
+ "memcpy_s : memory overlaps", ret);
+ } else {
+ memcpy(s1, s2, lim);
+ ret = 0;
+ }
+ } else {
+ /* trivial, do nothing */
+ ret = 0;
+ }
+ }
+ if (ret && zero_fill)
+ memset_s(s1, s1max, 0, s1max);
+ return (ret);
+}
Index: lib/libc/string/memmove_s.c
===================================================================
--- /dev/null
+++ lib/libc/string/memmove_s.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2017 Juniper Networks. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include "libc_private.h"
+
+/* ISO/IEC 9899:2011 K.3.7.1.2 */
+errno_t memmove_s(void * s1, rsize_t s1max, const void *s2, rsize_t n)
+{
+ rsize_t lim;
+ errno_t ret;
+ int zero_fill;
+
+ ret = EINVAL;
+ zero_fill = 0;
+
+ if (s1 == NULL) {
+ __throw_constraint_handler_s("memmove_s : s1 is NULL", ret);
+ } else if (s1max > RSIZE_MAX) {
+ __throw_constraint_handler_s("memmove_s : s1max > RSIZE_MAX",
+ ret);
+ } else if (s2 == NULL) {
+ zero_fill = 1;
+ __throw_constraint_handler_s("memmove_s : s2 is NULL", ret);
+ } else if (n > RSIZE_MAX) {
+ zero_fill = 1;
+ __throw_constraint_handler_s("memmove_s : n > RSIZE_MAX", ret);
+ } else {
+ lim = s1max;
+ if (n < s1max)
+ lim = n;
+ /* assume trival noop */
+ ret = 0;
+ if (lim > 0)
+ memmove(s1, s2, lim);
+ }
+ if (ret && zero_fill)
+ memset_s(s1, s1max, 0, s1max);
+ return (ret);
+}
Index: lib/libc/string/strcat_s.c
===================================================================
--- /dev/null
+++ lib/libc/string/strcat_s.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2017 Juniper Networks. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include "libc_private.h"
+
+/* ISO/IEC 9899:2011 K.3.7.2.1 */
+errno_t strcat_s(char * __restrict s1, rsize_t s1max,
+ const char * __restrict s2)
+{
+ rsize_t lim;
+ uintptr_t s1e, s2e;
+ errno_t ret;
+ size_t m, n;
+ int zero_fill;
+
+ ret = EINVAL;
+ zero_fill = 0;
+ if (s1 == NULL) {
+ __throw_constraint_handler_s("strcat_s : s1 is NULL", ret);
+ } else if (s1max > RSIZE_MAX) {
+ __throw_constraint_handler_s("strcat_s : s1max > RSIZE_MAX",
+ ret);
+ } else if (s1max == 0) {
+ __throw_constraint_handler_s("strcat_s : s1max == 0", ret);
+ } else if (s2 == NULL) {
+ zero_fill = 1;
+ __throw_constraint_handler_s("strcat_s : s2 is NULL", ret);
+ } else {
+ m = s1max - strnlen_s(s1, s1max);
+ if (m == 0) {
+ zero_fill = 1;
+ __throw_constraint_handler_s("strcat_s : s1 is full",
+ ret);
+ } else {
+ n = strnlen_s(s2, m);
+ if (n >= m) {
+ zero_fill = 1;
+ __throw_constraint_handler_s(
+ "strcat_s : s1 will overflow", ret);
+ } else {
+ lim = n;
+ if (lim > 0) {
+ s1e = (uintptr_t) s1 + m;
+ s2e = (uintptr_t) s2 + n;
+ if (((uintptr_t) s1 >=
+ (uintptr_t) s2 &&
+ (uintptr_t) s1 < s2e) ||
+ ((uintptr_t) s2 >=
+ (uintptr_t) s1 &&
+ (uintptr_t) s2 < s1e)) {
+ zero_fill = 1;
+ __throw_constraint_handler_s(
+ "strcat_s : memory overlaps", ret);
+ } else {
+ strncat(s1, s2, lim);
+ ret = 0;
+ }
+ } else {
+ /* trivial noop */
+ ret = 0;
+ }
+ }
+ }
+ }
+ /* do not zero fill on overlapping starts */
+ if (ret && zero_fill && s1 != s2)
+ s1[0] = 0;
+ return (ret);
+}
Index: lib/libc/string/strcpy_s.c
===================================================================
--- /dev/null
+++ lib/libc/string/strcpy_s.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2017 Juniper Networks. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include "libc_private.h"
+
+/* ISO/IEC 9899:2011 K.3.7.1.3 */
+errno_t strcpy_s(char * __restrict s1, rsize_t s1max,
+ const char * __restrict s2)
+{
+ rsize_t lim;
+ uintptr_t s1e, s2e;
+ errno_t ret;
+ int zero_fill;
+ size_t n;
+
+ ret = EINVAL;
+ zero_fill = 0;
+ if (s1 == NULL) {
+ __throw_constraint_handler_s("strcpy_s : s1 is NULL", ret);
+ } else if (s1max > RSIZE_MAX) {
+ __throw_constraint_handler_s("strcpy_s : s1max > RSIZE_MAX",
+ ret);
+ } else if (s1max == 0) {
+ __throw_constraint_handler_s("strcpy_s : s1max == 0", ret);
+ } else if (s2 == NULL) {
+ zero_fill = 1;
+ __throw_constraint_handler_s("strcpy_s : s2 is NULL", ret);
+ } else {
+ lim = s1max;
+ /*
+ * number of char's
+ * slmax -1 to account for the +1 added to result for
+ * null terminator. If it turns out there isn't a null
+ * terminator then the truncation will take care of
+ * reporting the error.
+ */
+ n = strnlen_s(s2, s1max - 1);
+ /* +1 to include null terminator */
+ n++;
+ if (n < s1max)
+ lim = n;
+ if (lim > 0) {
+ s1e = (uintptr_t) s1 + lim;
+ s2e = (uintptr_t) s2 + lim;
+ if (((uintptr_t) s1 >= (uintptr_t) s2 &&
+ (uintptr_t) s1 < s2e) ||
+ ((uintptr_t) s2 >= (uintptr_t) s1 &&
+ (uintptr_t) s2 < s1e)) {
+ /* do not zero fill on overlapping starts */
+ if (s1 != s2)
+ zero_fill = 1;
+ __throw_constraint_handler_s(
+ "strcpy_s : memory overlaps", ret);
+ } else {
+ if (n == s1max && s2[s1max -1] != 0) {
+ zero_fill = 1;
+ __throw_constraint_handler_s(
+ "strcpy_s : s2 will be truncated",
+ ret);
+ } else {
+ strncpy(s1, s2, lim);
+ ret = 0;
+ }
+ }
+ }
+ }
+ if (ret && zero_fill)
+ s1[0] = 0;
+ return (ret);
+}
Index: lib/libc/string/strerror_s.c
===================================================================
--- /dev/null
+++ lib/libc/string/strerror_s.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2017 Juniper Networks. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include "libc_private.h"
+
+/* ISO/IEC 9899:2011 K.3.7.4.2 */
+errno_t strerror_s(char *s, rsize_t maxsize, errno_t errnum)
+{
+ errno_t ret;
+ size_t err_len;
+ char *err_str;
+ char *e = "...";
+
+ ret = EINVAL;
+ if (s == NULL) {
+ __throw_constraint_handler_s("strerror_s : s is NULL", ret);
+ } else if (maxsize > RSIZE_MAX) {
+ __throw_constraint_handler_s(
+ "strerror_s : maxsize > RSIZE_MAX", ret);
+ } else if (maxsize == 0) {
+ __throw_constraint_handler_s("strerror_s : maxsize == 0", ret);
+ } else {
+ err_len = strerrorlen_s(errnum)+1;
+ err_str = strerror(errnum);
+ if (err_len <= maxsize) {
+ strcpy_s(s, err_len, err_str);
+ ret = 0;
+ } else {
+ if (maxsize < 5) {
+ strcpy_s(s, maxsize, &e[4-maxsize]);
+ } else {
+ /*
+ * err_str is going to be truncated
+ * use normal call
+ */
+ strncpy(s, err_str, maxsize - 4);
+ /*
+ * strncpy does not null terminate
+ * so advance to end
+ */
+ strcpy_s(&s[maxsize - 4], 4, e);
+ }
+ }
+ }
+ return (ret);
+}
Index: lib/libc/string/strerrorlen_s.c
===================================================================
--- /dev/null
+++ lib/libc/string/strerrorlen_s.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 Juniper Networks. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+#include "libc_private.h"
+
+/* ISO/IEC 9899:2011 K.3.7.4.3 */
+size_t strerrorlen_s(errno_t errnum)
+{
+ size_t ret;
+ char *e;
+
+ ret = 0;
+ e = strerror(errnum);
+ if (e != NULL)
+ ret = strlen(e);
+ return (ret);
+}
Index: lib/libc/string/strncat_s.c
===================================================================
--- /dev/null
+++ lib/libc/string/strncat_s.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2017 Juniper Networks. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include "libc_private.h"
+
+/* ISO/IEC 9899:2011 K.3.7.2.2 */
+errno_t strncat_s(char * __restrict s1, rsize_t s1max,
+ const char * __restrict s2, rsize_t n)
+{
+ rsize_t lim;
+ uintptr_t s1e, s2e;
+ errno_t ret;
+ size_t m, o;
+ int zero_fill;
+
+ ret = EINVAL;
+ zero_fill = 0;
+ if (s1 == NULL) {
+ __throw_constraint_handler_s("strncat_s : s1 is NULL", ret);
+ } else if (s1max > RSIZE_MAX) {
+ __throw_constraint_handler_s("strncat_s : s1max > RSIZE_MAX",
+ ret);
+ } else if (s1max == 0) {
+ __throw_constraint_handler_s("strncat_s : s1max == 0", ret);
+ } else if (s2 == NULL) {
+ zero_fill = 1;
+ __throw_constraint_handler_s("strncat_s : s2 is NULL", ret);
+ } else if (n > RSIZE_MAX) {
+ zero_fill = 1;
+ __throw_constraint_handler_s("strncat_s : n > RSIZE_MAX", ret);
+ } else {
+ m = s1max - strnlen_s(s1, s1max);
+ if (m == 0) {
+ zero_fill = 1;
+ __throw_constraint_handler_s(
+ "strncat_s : s1 is full", ret);
+ } else {
+ o = strnlen_s(s2, n);
+ if (o >= m) {
+ zero_fill = 1;
+ __throw_constraint_handler_s(
+ "strncat_s : s1 will overflow", ret);
+ } else {
+ lim = o;
+ if (lim > 0) {
+ s1e = (uintptr_t) s1 + m;
+ s2e = (uintptr_t) s2 + o;
+ if (((uintptr_t) s1 >=
+ (uintptr_t) s2 &&
+ (uintptr_t) s1 < s2e) ||
+ ((uintptr_t) s2 >=
+ (uintptr_t) s1 &&
+ (uintptr_t) s2 < s1e)) {
+ zero_fill = 1;
+ __throw_constraint_handler_s("strncat_s : memory overlaps", ret);
+ } else {
+ strncat(s1, s2, lim);
+ ret = 0;
+ }
+ } else {
+ /* trivial noop */
+ ret = 0;
+ }
+ }
+ }
+ }
+ /* do not zero fill on overlapping starts */
+ if (ret && zero_fill && s1 != s2)
+ s1[0] = 0;
+ return (ret);
+}
Index: lib/libc/string/strncpy_s.c
===================================================================
--- /dev/null
+++ lib/libc/string/strncpy_s.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2017 Juniper Networks. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include "libc_private.h"
+
+/* ISO/IEC 9899:2011 K.3.7.1.4 */
+errno_t strncpy_s(char * __restrict s1, rsize_t s1max,
+ const char * __restrict s2, rsize_t n)
+{
+ rsize_t lim;
+ uintptr_t s1e, s2e;
+ errno_t ret;
+ int zero_fill;
+ size_t s, t;
+
+ ret = EINVAL;
+ zero_fill = 0;
+ if (s1 == NULL) {
+ __throw_constraint_handler_s("strncpy_s : s1 is NULL", ret);
+ } else if (s1max > RSIZE_MAX) {
+ __throw_constraint_handler_s("strncpy_s : s1max > RSIZE_MAX",
+ ret);
+ } else if (s1max == 0) {
+ __throw_constraint_handler_s("strncpy_s : s1max == 0", ret);
+ } else if (s2 == NULL) {
+ zero_fill = 1;
+ __throw_constraint_handler_s("strncpy_s : s2 is NULL", ret);
+ } else {
+ lim = s1max;
+ /* assume s2 size will be ok */
+ s = n;
+ /*
+ * reset s2 size if n > s1max
+ *
+ * the '=' handles this corner case:
+ * n == s1max and s2[n-1] != 0
+ * then s1 will not be null terminated
+ */
+ if (n >= s1max) {
+ /*
+ * number of char's
+ * slmax -1 to account for the +1 added to result for
+ * null terminator.
+ */
+ s = strnlen_s(s2, s1max - 1);
+ /* +1 to include null terminator */
+ s++;
+ }
+ if (s < s1max)
+ lim = s;
+ if (lim > 0) {
+ s1e = (uintptr_t) s1 + lim;
+ s2e = (uintptr_t) s2 + lim;
+ if (((uintptr_t) s1 >= (uintptr_t) s2 &&
+ (uintptr_t) s1 < s2e) ||
+ ((uintptr_t) s2 >= (uintptr_t) s1 &&
+ (uintptr_t) s2 < s1e)) {
+ /* do not zero fill on overlapping starts */
+ if (s1 != s2)
+ zero_fill = 1;
+ __throw_constraint_handler_s(
+ "strncpy_s : memory overlaps", ret);
+ } else {
+ if (s == s1max && s2[s1max -1] != 0) {
+ zero_fill = 1;
+ /*
+ * Do not have a special throw string
+ * for n == s1max corner case
+ */
+ __throw_constraint_handler_s(
+ "strncpy_s : s2 will be truncated",
+ ret);
+ } else {
+ /* strncpy does not null terminate. */
+ for (t = 0; t < lim; t++) {
+ if (s2[t] == 0)
+ break;
+ s1[t] = s2[t];
+ }
+ s1[t] = 0;
+ ret = 0;
+ }
+ }
+ } else {
+ /* trivial, still need to null terminate */
+ s1[0] = 0;
+ ret = 0;
+ }
+ }
+ if (ret && zero_fill)
+ s1[0] = 0;
+ return (ret);
+}
Index: lib/libc/string/strnlen_s.c
===================================================================
--- /dev/null
+++ lib/libc/string/strnlen_s.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017 Juniper Networks. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+#include "libc_private.h"
+
+/* ISO/IEC 9899:2011 K.3.7.4.4 */
+size_t strnlen_s(const char *s, size_t maxsize)
+{
+ size_t ret;
+
+ ret = 0;
+ if (s != NULL)
+ ret = strnlen(s, maxsize);
+ return (ret);
+}
Index: lib/libc/string/strtok_s.c
===================================================================
--- /dev/null
+++ lib/libc/string/strtok_s.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2017 Juniper Networks. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include "libc_private.h"
+
+static int _check_first(char a, const char *b, size_t n)
+{
+ int ret;
+ size_t i;
+
+ ret = 1;
+ for (i = 0; i < n; i++) {
+ if (a == b[i]) {
+ ret = 0;
+ break;
+ }
+ }
+ return (ret);
+}
+
+static void _setptr_first(char *a, size_t i, size_t max __unused, char **b)
+{
+ *b = a + i;
+}
+
+static void _setret_first(char *cur, size_t i, char **ret)
+{
+ *ret = &cur[i];
+}
+
+static void _setmax_first(rsize_t *max, size_t i, size_t lim)
+{
+ *max = lim - i;
+}
+
+static int _check_next(char a, const char *b, size_t n)
+{
+ int ret;
+ size_t i;
+
+ ret = 0;
+ for (i = 0; i < n; i++) {
+ if (a == b[i]) {
+ ret = 1;
+ break;
+ }
+ }
+ return (ret);
+}
+
+static void _setptr_next(char *a, size_t i, size_t max, char **b)
+{
+ a[i] = 0;
+ if (i+1 < max)
+ *b = &a[i + 1];
+}
+
+static void _setret_next(char *cur, size_t i __unused, char **ret)
+{
+ *ret = cur;
+}
+
+static void _setmax_next(rsize_t *max, size_t i, size_t lim)
+{
+ if (i < lim)
+ *max = lim - i - 1;
+ else
+ *max = 0;
+}
+
+/* ISO/IEC 9899:2011 K.3.7.3.1 */
+char *strtok_s(char * __restrict s1, rsize_t * __restrict s1max,
+ const char * __restrict s2, char ** __restrict ptr)
+{
+ char *ret, *cur;
+ rsize_t i, lim, s2len;
+ int (*check)(char, const char *, size_t);
+ void (*setptr)(char *, size_t, size_t, char **);
+ void (*setret)(char *, size_t, char **);
+ void (*setmax)(rsize_t *, size_t, size_t);
+
+ ret = NULL;
+ if (s1max == NULL) {
+ __throw_constraint_handler_s("strtok_s : s1max is NULL",
+ EINVAL);
+ } else if (s2 == NULL) {
+ __throw_constraint_handler_s("strtok_s : s2 is NULL", EINVAL);
+ } else if (ptr == NULL) {
+ __throw_constraint_handler_s("strtok_s : ptr is NULL", EINVAL);
+ } else if (s1 == NULL && *ptr == NULL) {
+ __throw_constraint_handler_s("strtok_s : *ptr is NULL",
+ EINVAL);
+ } else if (*s1max > RSIZE_MAX) {
+ __throw_constraint_handler_s("strtok_s : *s1max > RSIZE_MAX",
+ EINVAL);
+ } else {
+ s2len = strlen(s2);
+ if (s2len != 0) {
+ if (s1 != NULL) {
+ cur = s1;
+ check = _check_first;
+ setptr = _setptr_first;
+ setret = _setret_first;
+ setmax = _setmax_first;
+ } else {
+ cur = *ptr;
+ check = _check_next;
+ setptr = _setptr_next;
+ setret = _setret_next;
+ setmax = _setmax_next;
+ }
+ lim = *s1max;
+ *ptr = NULL;
+ for (i = 0; i < lim; i++) {
+ if (check(cur[i], s2, s2len)) {
+ setptr(cur, i, lim, ptr);
+ break;
+ }
+ }
+ if (i < lim)
+ setret(cur, i, &ret);
+ setmax(s1max, i, lim);
+ }
+ }
+ return (ret);
+}
Index: lib/libc/tests/string/Makefile
===================================================================
--- lib/libc/tests/string/Makefile
+++ lib/libc/tests/string/Makefile
@@ -1,14 +1,24 @@
# $FreeBSD$
+ATF_TESTS_C+= memcpy_s_test
ATF_TESTS_C+= memcmp_test
+ATF_TESTS_C+= memmove_s_test
ATF_TESTS_C+= memset_s_test
ATF_TESTS_C+= stpncpy_test
+ATF_TESTS_C+= strcat_s_test
+ATF_TESTS_C+= strcpy_s_test
ATF_TESTS_C+= strerror2_test
+ATF_TESTS_C+= strerror_s_test
+ATF_TESTS_C+= strncat_s_test
+ATF_TESTS_C+= strncpy_s_test
+ATF_TESTS_C+= strnlen_s_test
+ATF_TESTS_C+= strtok_s_test
ATF_TESTS_C+= wcscasecmp_test
ATF_TESTS_C+= wcsnlen_test
ATF_TESTS_C+= strxfrm_test
ATF_TESTS_C+= wcscoll_test
+
# TODO: popcount, stresep
NETBSD_ATF_TESTS_C+= memchr_test
Index: lib/libc/tests/string/memcpy_s_test.c
===================================================================
--- /dev/null
+++ lib/libc/tests/string/memcpy_s_test.c
@@ -0,0 +1,467 @@
+/*-
+ * Copyright (c) 2017 Juniper Networks. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <atf-c.h>
+
+static errno_t e;
+static const char * restrict m;
+
+void
+h(const char * restrict msg, void * restrict ptr __unused, errno_t error)
+{
+ e = error;
+ m = msg;
+}
+
+/* s1 null ptr */
+ATF_TC_WITHOUT_HEAD(s1_null_ptr);
+ATF_TC_BODY(s1_null_ptr, tc)
+{
+ char b;
+
+ b = 5;
+ assert(memcpy_s(0, 1, &b, 1) != 0);
+ assert(b == 5);
+}
+
+/* s1max > rmax */
+ATF_TC_WITHOUT_HEAD(s1max_gt_rmax);
+ATF_TC_BODY(s1max_gt_rmax, tc)
+{
+ char a, b;
+
+ a = 3;
+ b = 5;
+ assert(memcpy_s(&a, RSIZE_MAX + 1, &b, 1) != 0);
+ assert(a == 3);
+ assert(b == 5);
+}
+
+/* s1max < 0 */
+ATF_TC_WITHOUT_HEAD(s1max_lt_0);
+ATF_TC_BODY(s1max_lt_0, tc)
+{
+ char a, b;
+
+ a = 3;
+ b = 5;
+ assert(memcpy_s(&a, -1, &b, 1) != 0);
+ assert(a == 3);
+ assert(b == 5);
+}
+
+/* normal */
+ATF_TC_WITHOUT_HEAD(normal);
+ATF_TC_BODY(normal, tc)
+{
+ char a, b;
+
+ a = 3;
+ b = 5;
+ assert(memcpy_s(&a, 1, &b, 1) == 0);
+ assert(a == 5);
+ assert(b == 5);
+}
+
+/* s2 null ptr */
+ATF_TC_WITHOUT_HEAD(s2_null_ptr);
+ATF_TC_BODY(s2_null_ptr, tc)
+{
+ char a;
+
+ a = 5;
+ assert(memcpy_s(&a, 1, 0, 1) != 0);
+ assert(a == 0);
+}
+
+/* n > rmax */
+ATF_TC_WITHOUT_HEAD(n_gt_rmax);
+ATF_TC_BODY(n_gt_rmax, tc)
+{
+ char a, b;
+
+ a = 3;
+ b = 5;
+ assert(memcpy_s(&a, 1, &b, RSIZE_MAX + 1) != 0);
+ assert(a == 0);
+ assert(b == 5);
+}
+
+/* n < 0 */
+ATF_TC_WITHOUT_HEAD(n_lt_0);
+ATF_TC_BODY(n_lt_0, tc)
+{
+ char a, b;
+
+ a = 3;
+ b = 5;
+ assert(memcpy_s(&a, 1, &b, -1) != 0);
+ assert(a == 0);
+ assert(b == 5);
+}
+
+/* n < s1max */
+ATF_TC_WITHOUT_HEAD(n_lt_s1max);
+ATF_TC_BODY(n_lt_s1max, tc)
+{
+ char a[3] = { 1, 2, 3 };
+ char b[3] = { 5, 6, 7 };
+
+ assert(memcpy_s(&a[0], 3, &b[0], 2) == 0);
+ assert(a[0] == 5);
+ assert(a[1] == 6);
+ assert(a[2] == 3);
+}
+
+/* n > s1max */
+ATF_TC_WITHOUT_HEAD(n_gt_s1max);
+ATF_TC_BODY(n_gt_s1max, tc)
+{
+ char a[3] = { 1, 2, 3 };
+ char b[3] = { 5, 6, 7 };
+
+ assert(memcpy_s(&a[0], 2, &b[0], 3) == 0);
+ assert(a[0] == 5);
+ assert(a[1] == 6);
+ assert(a[2] == 3);
+}
+
+/* null ptr, handler */
+ATF_TC_WITHOUT_HEAD(s1_null_ptr_handler);
+ATF_TC_BODY(s1_null_ptr_handler, tc)
+{
+ char b;
+
+ b = 5;
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(memcpy_s(0, 1, &b, 1) != 0);
+ assert(e != 0);
+ assert(0 == strcmp(m, "memcpy_s : s1 is NULL"));
+}
+
+/* s1max > rmax, handler */
+ATF_TC_WITHOUT_HEAD(s1max_gt_rmax_handler);
+ATF_TC_BODY(s1max_gt_rmax_handler, tc)
+{
+ char a, b;
+
+ a = 3;
+ b = 5;
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(memcpy_s(&b, RSIZE_MAX + 1, &b, 1) != 0);
+ assert(a == 3);
+ assert(b == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "memcpy_s : s1max > RSIZE_MAX"));
+}
+
+/* s1max < 0, handler */
+ATF_TC_WITHOUT_HEAD(s1max_lt_0_handler);
+ATF_TC_BODY(s1max_lt_0_handler, tc)
+{
+ char a, b;
+
+ a = 3;
+ b = 5;
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(memcpy_s(&b, -1, &b, 1) != 0);
+ assert(a == 3);
+ assert(b == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "memcpy_s : s1max > RSIZE_MAX"));
+}
+
+/* normal, handler */
+ATF_TC_WITHOUT_HEAD(normal_handler);
+ATF_TC_BODY(normal_handler, tc)
+{
+ char a, b;
+
+ a = 3;
+ b = 5;
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(memcpy_s(&a, 1, &b, 1) == 0);
+ assert(a == 5);
+ assert(b == 5);
+ assert(e == 0);
+ assert(m == NULL);
+}
+
+/* s2 null ptr, handler */
+ATF_TC_WITHOUT_HEAD(s2_null_ptr_handler);
+ATF_TC_BODY(s2_null_ptr_handler, tc)
+{
+ char a;
+
+ a = 5;
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(memcpy_s(&a, 1, 0, 1) != 0);
+ assert(a == 0);
+ assert(e != 0);
+ assert(0 == strcmp(m, "memcpy_s : s2 is NULL"));
+}
+
+/* n > rmax, handler */
+ATF_TC_WITHOUT_HEAD(n_gt_rmax_handler);
+ATF_TC_BODY(n_gt_rmax_handler, tc)
+{
+ char a, b;
+
+ a = 3;
+ b = 5;
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(memcpy_s(&a, 1, &b, RSIZE_MAX + 1) != 0);
+ assert(a == 0);
+ assert(b == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "memcpy_s : n > RSIZE_MAX"));
+}
+
+/* n < 0, handler */
+ATF_TC_WITHOUT_HEAD(n_lt_0_handler);
+ATF_TC_BODY(n_lt_0_handler, tc)
+{
+ char a, b;
+
+ a = 3;
+ b = 5;
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(memcpy_s(&a, 1, &b, -1) != 0);
+ assert(a == 0);
+ assert(b == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "memcpy_s : n > RSIZE_MAX"));
+}
+
+/* overlap, beginning */
+ATF_TC_WITHOUT_HEAD(overlap_beginning);
+ATF_TC_BODY(overlap_beginning, tc)
+{
+ char a[6] = { 1, 2, 3, 4, 5, 6 };
+
+ assert(memcpy_s(&a[0], 1, &a[0], 1) != 0);
+ assert(a[0] == 1);
+}
+
+/* overlap, ending 1 */
+ATF_TC_WITHOUT_HEAD(overlap_ending_1);
+ATF_TC_BODY(overlap_ending_1, tc)
+{
+ char a[6] = { 1, 2, 3, 4, 5, 6 };
+
+ assert(memcpy_s(&a[0], 3, &a[2], 3) != 0);
+ assert(a[0] == 1);
+ assert(a[1] == 2);
+ assert(a[2] == 3);
+}
+
+/* overlap, ending 2 */
+ATF_TC_WITHOUT_HEAD(overlap_ending_2);
+ATF_TC_BODY(overlap_ending_2, tc)
+{
+ char a[6] = { 1, 2, 3, 4, 5, 6 };
+
+ assert(memcpy_s(&a[2], 3, &a[0], 3) != 0);
+ assert(a[0] == 1);
+ assert(a[1] == 2);
+ assert(a[2] == 3);
+}
+
+/* overlap, beginning, handler */
+ATF_TC_WITHOUT_HEAD(overlap_beginning_handler);
+ATF_TC_BODY(overlap_beginning_handler, tc)
+{
+ char a[6] = { 1, 2, 3, 4, 5, 6 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(memcpy_s(&a[0], 1, &a[0], 1) != 0);
+ assert(a[0] == 1);
+ assert(e != 0);
+ assert(0 == strcmp(m, "memcpy_s : memory overlaps"));
+}
+
+/* overlap, ending 1, handler */
+ATF_TC_WITHOUT_HEAD(overlap_ending_1_handler);
+ATF_TC_BODY(overlap_ending_1_handler, tc)
+{
+ char a[6] = { 1, 2, 3, 4, 5, 6 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(memcpy_s(&a[0], 3, &a[2], 3) != 0);
+ assert(a[0] == 1);
+ assert(a[1] == 2);
+ assert(a[2] == 3);
+ assert(e != 0);
+ assert(0 == strcmp(m, "memcpy_s : memory overlaps"));
+}
+
+/* overlap, ending 2, handler */
+ATF_TC_WITHOUT_HEAD(overlap_ending_2_handler);
+ATF_TC_BODY(overlap_ending_2_handler, tc)
+{
+ char a[6] = { 1, 2, 3, 4, 5, 6 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(memcpy_s(&a[2], 3, &a[0], 3) != 0);
+ assert(a[0] == 1);
+ assert(a[1] == 2);
+ assert(a[2] == 3);
+ assert(e != 0);
+ assert(0 == strcmp(m, "memcpy_s : memory overlaps"));
+}
+
+/* no overlap 1 */
+ATF_TC_WITHOUT_HEAD(no_overlap_1);
+ATF_TC_BODY(no_overlap_1, tc)
+{
+ char a[6] = { 1, 2, 3, 4, 5, 6 };
+
+ assert(memcpy_s(&a[0], 1, &a[1], 1) == 0);
+ assert(a[0] == 2);
+}
+
+/* no overlap 2 */
+ATF_TC_WITHOUT_HEAD(no_overlap_2);
+ATF_TC_BODY(no_overlap_2, tc)
+{
+ char a[6] = { 1, 2, 3, 4, 5, 6 };
+
+ assert(memcpy_s(&a[1], 1, &a[0], 1) == 0);
+ assert(a[1] == 1);
+}
+
+/* no overlap 3 */
+ATF_TC_WITHOUT_HEAD(no_overlap_3);
+ATF_TC_BODY(no_overlap_3, tc)
+{
+ char a[6] = { 1, 2, 3, 4, 5, 6 };
+
+ assert(memcpy_s(&a[0], 2, &a[2], 2) == 0);
+ assert(a[0] == 3);
+ assert(a[1] == 4);
+}
+
+/* no overlap 4 */
+ATF_TC_WITHOUT_HEAD(no_overlap_4);
+ATF_TC_BODY(no_overlap_4, tc)
+{
+ char a[6] = { 1, 2, 3, 4, 5, 6 };
+
+ assert(memcpy_s(&a[2], 2, &a[0], 2) == 0);
+ assert(a[2] == 1);
+ assert(a[3] == 2);
+}
+
+/* overlap, middle 1, handler */
+ATF_TC_WITHOUT_HEAD(overlap_middle_1_handler);
+ATF_TC_BODY(overlap_middle_1_handler, tc)
+{
+ char a[6] = { 1, 2, 3, 4, 5, 6 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(memcpy_s(&a[0], 4, &a[1], 2) != 0);
+ assert(a[0] == 1);
+ assert(a[1] == 2);
+ assert(a[2] == 3);
+ assert(e != 0);
+ assert(0 == strcmp(m, "memcpy_s : memory overlaps"));
+}
+
+/* noop */
+ATF_TC_WITHOUT_HEAD(noop);
+ATF_TC_BODY(noop, tc)
+{
+ char a, b;
+
+ a = 3;
+ b = 5;
+ assert(memcpy_s(&a, 1, &b, 0) == 0);
+ assert(a == 3);
+ assert(b == 5);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, s1_null_ptr);
+ ATF_TP_ADD_TC(tp, s1max_gt_rmax);
+ ATF_TP_ADD_TC(tp, s1max_lt_0);
+ ATF_TP_ADD_TC(tp, normal);
+ ATF_TP_ADD_TC(tp, s2_null_ptr);
+ ATF_TP_ADD_TC(tp, n_gt_rmax);
+ ATF_TP_ADD_TC(tp, n_lt_0);
+ ATF_TP_ADD_TC(tp, n_lt_s1max);
+ ATF_TP_ADD_TC(tp, n_gt_s1max);
+ ATF_TP_ADD_TC(tp, s1_null_ptr_handler);
+ ATF_TP_ADD_TC(tp, s1max_gt_rmax_handler);
+ ATF_TP_ADD_TC(tp, s1max_lt_0_handler);
+ ATF_TP_ADD_TC(tp, normal_handler);
+ ATF_TP_ADD_TC(tp, s2_null_ptr_handler);
+ ATF_TP_ADD_TC(tp, n_gt_rmax_handler);
+ ATF_TP_ADD_TC(tp, n_lt_0_handler);
+ ATF_TP_ADD_TC(tp, overlap_beginning);
+ ATF_TP_ADD_TC(tp, overlap_ending_1);
+ ATF_TP_ADD_TC(tp, overlap_ending_2);
+ ATF_TP_ADD_TC(tp, overlap_beginning_handler);
+ ATF_TP_ADD_TC(tp, overlap_ending_1_handler);
+ ATF_TP_ADD_TC(tp, overlap_ending_2_handler);
+ ATF_TP_ADD_TC(tp, no_overlap_1);
+ ATF_TP_ADD_TC(tp, no_overlap_2);
+ ATF_TP_ADD_TC(tp, no_overlap_3);
+ ATF_TP_ADD_TC(tp, no_overlap_4);
+ ATF_TP_ADD_TC(tp, overlap_middle_1_handler);
+ ATF_TP_ADD_TC(tp, noop);
+ return (atf_no_error());
+}
+
Index: lib/libc/tests/string/memmove_s_test.c
===================================================================
--- /dev/null
+++ lib/libc/tests/string/memmove_s_test.c
@@ -0,0 +1,298 @@
+/*-
+ * Copyright (c) 2017 Juniper Networks. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <atf-c.h>
+
+static errno_t e;
+static const char * restrict m;
+
+void
+h(const char * restrict msg, void * restrict ptr __unused, errno_t error)
+{
+ e = error;
+ m = msg;
+}
+
+/* s1 null ptr */
+ATF_TC_WITHOUT_HEAD(s1_null_ptr);
+ATF_TC_BODY(s1_null_ptr, tc)
+{
+ char b;
+
+ b = 5;
+ assert(memmove_s(0, 1, &b, 1) != 0);
+ assert(b == 5);
+}
+
+/* s1max > rmax */
+ATF_TC_WITHOUT_HEAD(s1max_gt_rmax);
+ATF_TC_BODY(s1max_gt_rmax, tc)
+{
+ char a, b;
+
+ a = 3;
+ b = 5;
+ assert(memmove_s(&b, RSIZE_MAX + 1, &b, 1) != 0);
+ assert(a == 3);
+ assert(b == 5);
+}
+
+/* s1max < 0 */
+ATF_TC_WITHOUT_HEAD(s1max_lt_0);
+ATF_TC_BODY(s1max_lt_0, tc)
+{
+ char a, b;
+
+ a = 3;
+ b = 5;
+ assert(memmove_s(&b, -1, &b, 1) != 0);
+ assert(a == 3);
+ assert(b == 5);
+}
+
+/* normal */
+ATF_TC_WITHOUT_HEAD(normal);
+ATF_TC_BODY(normal, tc)
+{
+ char a, b;
+
+ a = 3;
+ b = 5;
+ assert(memmove_s(&a, 1, &b, 1) == 0);
+ assert(a == 5);
+ assert(b == 5);
+}
+
+/* s2 null ptr */
+ATF_TC_WITHOUT_HEAD(s2_null_ptr);
+ATF_TC_BODY(s2_null_ptr, tc)
+{
+ char a;
+
+ a = 5;
+ assert(memmove_s(&a, 1, 0, 1) != 0);
+ assert(a == 0);
+}
+
+/* n > rmax */
+ATF_TC_WITHOUT_HEAD(n_gt_rmax);
+ATF_TC_BODY(n_gt_rmax, tc)
+{
+ char a, b;
+
+ a = 3;
+ b = 5;
+ assert(memmove_s(&a, 1, &b, RSIZE_MAX + 1) != 0);
+ assert(a == 0);
+ assert(b == 5);
+}
+
+/* n < 0 */
+ATF_TC_WITHOUT_HEAD(n_lt_0);
+ATF_TC_BODY(n_lt_0, tc)
+{
+ char a, b;
+
+ a = 3;
+ b = 5;
+ assert(memmove_s(&a, 1, &b, -1) != 0);
+ assert(a == 0);
+ assert(b == 5);
+}
+
+/* n < s1max */
+ATF_TC_WITHOUT_HEAD(n_lt_s1max);
+ATF_TC_BODY(n_lt_s1max, tc)
+{
+ char a[3] = { 1, 2, 3 };
+ char b[3] = { 5, 6, 7 };
+ assert(memmove_s(&a[0], 3, &b[0], 2) == 0);
+ assert(a[0] == 5);
+ assert(a[1] == 6);
+ assert(a[2] == 3);
+}
+
+/* n > s1max */
+ATF_TC_WITHOUT_HEAD(n_gt_s1max);
+ATF_TC_BODY(n_gt_s1max, tc)
+{
+ char a[3] = { 1, 2, 3 };
+ char b[3] = { 5, 6, 7 };
+
+ assert(memmove_s(&a[0], 2, &b[0], 3) == 0);
+ assert(a[0] == 5);
+ assert(a[1] == 6);
+ assert(a[2] == 3);
+}
+
+/* null ptr, handler */
+ATF_TC_WITHOUT_HEAD(s1_null_ptr_handler);
+ATF_TC_BODY(s1_null_ptr_handler, tc)
+{
+ char b;
+
+ b = 5;
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(memmove_s(0, 1, &b, 1) != 0);
+ assert(e != 0);
+ assert(0 == strcmp(m, "memmove_s : s1 is NULL"));
+}
+
+/* s1max > rmax, handler */
+ATF_TC_WITHOUT_HEAD(s1max_gt_rmax_handler);
+ATF_TC_BODY(s1max_gt_rmax_handler, tc)
+{
+ char a, b;
+
+ a = 3;
+ b = 5;
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(memmove_s(&b, RSIZE_MAX + 1, &b, 1) != 0);
+ assert(a == 3);
+ assert(b == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "memmove_s : s1max > RSIZE_MAX"));
+}
+
+/* s1max < 0, handler */
+ATF_TC_WITHOUT_HEAD(s1max_lt_0_handler);
+ATF_TC_BODY(s1max_lt_0_handler, tc)
+{
+ char a, b;
+
+ a = 3;
+ b = 5;
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(memmove_s(&b, -1, &b, 1) != 0);
+ assert(a == 3);
+ assert(b == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "memmove_s : s1max > RSIZE_MAX"));
+}
+
+/* normal, handler */
+ATF_TC_WITHOUT_HEAD(normal_handler);
+ATF_TC_BODY(normal_handler, tc)
+{
+ char a, b;
+
+ a = 3;
+ b = 5;
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(memmove_s(&a, 1, &b, 1) == 0);
+ assert(a == 5);
+ assert(b == 5);
+ assert(e == 0);
+ assert(m == NULL);
+}
+
+/* s2 null ptr, handler */
+ATF_TC_WITHOUT_HEAD(s2_null_ptr_handler);
+ATF_TC_BODY(s2_null_ptr_handler, tc)
+{
+ char a;
+
+ a = 5;
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(memmove_s(&a, 1, 0, 1) != 0);
+ assert(a == 0);
+ assert(e != 0);
+ assert(0 == strcmp(m, "memmove_s : s2 is NULL"));
+}
+
+/* n > rmax, handler */
+ATF_TC_WITHOUT_HEAD(n_gt_rmax_handler);
+ATF_TC_BODY(n_gt_rmax_handler, tc)
+{
+ char a, b;
+
+ a = 3;
+ b = 5;
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(memmove_s(&a, 1, &b, RSIZE_MAX + 1) != 0);
+ assert(a == 0);
+ assert(b == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "memmove_s : n > RSIZE_MAX"));
+}
+
+/* n < 0, handler */
+ATF_TC_WITHOUT_HEAD(n_lt_0_handler);
+ATF_TC_BODY(n_lt_0_handler, tc)
+{
+ char a, b;
+
+ a = 3;
+ b = 5;
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(memmove_s(&a, 1, &b, -1) != 0);
+ assert(a == 0);
+ assert(b == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "memmove_s : n > RSIZE_MAX"));
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, s1_null_ptr);
+ ATF_TP_ADD_TC(tp, s1max_gt_rmax);
+ ATF_TP_ADD_TC(tp, s1max_lt_0);
+ ATF_TP_ADD_TC(tp, normal);
+ ATF_TP_ADD_TC(tp, s2_null_ptr);
+ ATF_TP_ADD_TC(tp, n_gt_rmax);
+ ATF_TP_ADD_TC(tp, n_lt_0);
+ ATF_TP_ADD_TC(tp, n_lt_s1max);
+ ATF_TP_ADD_TC(tp, n_gt_s1max);
+ ATF_TP_ADD_TC(tp, s1_null_ptr_handler);
+ ATF_TP_ADD_TC(tp, s1max_gt_rmax_handler);
+ ATF_TP_ADD_TC(tp, s1max_lt_0_handler);
+ ATF_TP_ADD_TC(tp, normal_handler);
+ ATF_TP_ADD_TC(tp, s2_null_ptr_handler);
+ ATF_TP_ADD_TC(tp, n_gt_rmax_handler);
+ ATF_TP_ADD_TC(tp, n_lt_0_handler);
+ return (atf_no_error());
+}
Index: lib/libc/tests/string/strcat_s_test.c
===================================================================
--- /dev/null
+++ lib/libc/tests/string/strcat_s_test.c
@@ -0,0 +1,529 @@
+/*-
+ * Copyright (c) 2017 Juniper Networks. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <atf-c.h>
+
+static errno_t e;
+static const char * restrict m;
+
+void
+h(const char * restrict msg, void * restrict ptr __unused, errno_t error)
+{
+ e = error;
+ m = msg;
+}
+
+/* s1 null ptr */
+ATF_TC_WITHOUT_HEAD(s1_null_ptr);
+ATF_TC_BODY(s1_null_ptr, tc)
+{
+ char b[2] = { 5, 0 };
+
+ assert(strcat_s(0, 1, &b[0]) != 0);
+ assert(b[0] == 5);
+}
+
+/* s1max > rmax */
+ATF_TC_WITHOUT_HEAD(s1max_gt_rmax);
+ATF_TC_BODY(s1max_gt_rmax, tc)
+{
+ char a[2] = { 3, 0 };
+ char b[2] = { 5, 0 };
+
+ assert(strcat_s(&a[0], RSIZE_MAX + 1, &b[0]) != 0);
+ assert(a[0] == 3);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+}
+
+/* s1max < 0 */
+ATF_TC_WITHOUT_HEAD(s1max_lt_0);
+ATF_TC_BODY(s1max_lt_0, tc)
+{
+ char a[2] = { 3, 0 };
+ const char b[2] = { 5, 0 };
+
+ assert(strcat_s(&a[0], -1, &b[0]) != 0);
+ assert(a[0] == 3);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+}
+
+/* normal */
+ATF_TC_WITHOUT_HEAD(normal);
+ATF_TC_BODY(normal, tc)
+{
+ char a[4] = { 4, 0, 2, 1 };
+ char b[2] = { 5, 0 };
+
+ assert(strcat_s(&a[0], 4, &b[0]) == 0);
+ assert(a[0] == 4);
+ assert(a[1] == 5);
+ assert(a[2] == 0);
+ assert(b[0] == 5);
+}
+
+/* s2 null ptr */
+ATF_TC_WITHOUT_HEAD(s2_null_ptr);
+ATF_TC_BODY(s2_null_ptr, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+
+ assert(strcat_s(&a[0], 4, 0) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+}
+
+/* s1 full already, poor s1 */
+ATF_TC_WITHOUT_HEAD(s1_full_already_poor_s1);
+ATF_TC_BODY(s1_full_already_poor_s1, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+ char b[2] = { 5, 0 };
+
+ assert(strcat_s(&a[0], 4, &b[0]) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(b[0] == 5);
+}
+
+/* s1 full already, normal case */
+ATF_TC_WITHOUT_HEAD(s1_full_already_normal_case);
+ATF_TC_BODY(s1_full_already_normal_case, tc)
+{
+ char a[4] = { 4, 3, 2, 0 };
+ char b[2] = { 5, 0 };
+
+ assert(strcat_s(&a[0], 4, &b[0]) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(b[0] == 5);
+}
+
+/* s1 full already, but nothing to cat */
+ATF_TC_WITHOUT_HEAD(s1_full_already_but_nothing_to_cat);
+ATF_TC_BODY(s1_full_already_but_nothing_to_cat, tc)
+{
+ char a[4] = { 4, 3, 2, 0 };
+ char b[2] = { 0, 1 };
+
+ assert(strcat_s(&a[0], 4, &b[0]) == 0);
+ assert(a[0] == 4);
+ assert(a[3] == 0);
+ assert(b[0] == 0);
+}
+
+/* s1 will become full, not enough space for null terminator */
+ATF_TC_WITHOUT_HEAD(trunc_1);
+ATF_TC_BODY(trunc_1, tc)
+{
+ char a[4] = { 4, 3, 0, 1 };
+ char b[3] = { 5, 6, 0 };
+
+ assert(strcat_s(&a[0], 4, &b[0]) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(b[0] == 5);
+}
+
+/* s1 will become full, simple case */
+ATF_TC_WITHOUT_HEAD(trunc_2);
+ATF_TC_BODY(trunc_2, tc)
+{
+ char a[6] = { 4, 3, 0, 1, 2, 3 };
+ char b[5] = { 5, 6, 7, 8, 0 };
+
+ assert(strcat_s(&a[0], 6, &b[0]) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(b[0] == 5);
+}
+
+/* s1max == 0 */
+ATF_TC_WITHOUT_HEAD(s1max_eq_0);
+ATF_TC_BODY(s1max_eq_0, tc)
+{
+ char a[2] = { 3, 0 };
+ char b[2] = { 5, 0 };
+
+ assert(strcat_s(&a[0], 0, &b[0]) != 0);
+ assert(a[0] == 3);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+}
+
+/*
+ * s1 will become full,
+ * not enough space for null terminator,
+ * overlapping s1 and s2
+ */
+ATF_TC_WITHOUT_HEAD(complex_1);
+ATF_TC_BODY(complex_1, tc)
+{
+ char a[4] = { 4, 3, 0, 1 };
+
+ assert(strcat_s(&a[0], 4, &a[0]) != 0);
+ assert(a[0] == 4);
+ assert(a[1] == 3);
+}
+
+/* overlapping no zero fill */
+ATF_TC_WITHOUT_HEAD(overlapping_no_zero_fill);
+ATF_TC_BODY(overlapping_no_zero_fill, tc)
+{
+ char a[5] = { 4, 3, 0, 1, 0 };
+
+ assert(strcat_s(&a[0], 5, &a[0]) != 0);
+ assert(a[0] == 4);
+ assert(a[1] == 3);
+}
+
+/* overlapping zero fill */
+ATF_TC_WITHOUT_HEAD(overlapping_zero_fill);
+ATF_TC_BODY(overlapping_zero_fill, tc)
+{
+ char a[5] = { 4, 3, 0, 1, 0 };
+
+ assert(strcat_s(&a[0], 5, &a[1]) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+}
+
+/* overlapping, nothing to cat */
+ATF_TC_WITHOUT_HEAD(overlapping_nothing_to_cat);
+ATF_TC_BODY(overlapping_nothing_to_cat, tc)
+{
+ char a[5] = { 4, 3, 0, 1, 0 };
+
+ assert(strcat_s(&a[0], 5, &a[2]) == 0);
+ assert(a[0] == 4);
+ assert(a[2] == 0);
+}
+
+/* s1 null ptr, handler */
+ATF_TC_WITHOUT_HEAD(s1_null_ptr_handler);
+ATF_TC_BODY(s1_null_ptr_handler, tc)
+{
+ char b[2] = { 5, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strcat_s(0, 1, &b[0]) != 0);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strcat_s : s1 is NULL"));
+}
+
+/* s1max > rmax, handler */
+ATF_TC_WITHOUT_HEAD(s1max_gt_rmax_handler);
+ATF_TC_BODY(s1max_gt_rmax_handler, tc)
+{
+ char a[2] = { 3, 0 };
+ char b[2] = { 5, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strcat_s(&a[0], RSIZE_MAX + 1, &b[0]) != 0);
+ assert(a[0] == 3);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strcat_s : s1max > RSIZE_MAX"));
+}
+
+/* s1max < 0, handler */
+ATF_TC_WITHOUT_HEAD(s1max_lt_0_handler);
+ATF_TC_BODY(s1max_lt_0_handler, tc)
+{
+ char a[2] = { 3, 0 };
+ const char b[2] = { 5, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strcat_s(&a[0], -1, &b[0]) != 0);
+ assert(a[0] == 3);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strcat_s : s1max > RSIZE_MAX"));
+}
+
+/* normal, handler */
+ATF_TC_WITHOUT_HEAD(normal_handler);
+ATF_TC_BODY(normal_handler, tc)
+{
+ char a[4] = { 4, 0, 2, 1 };
+ char b[2] = { 5, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strcat_s(&a[0], 4, &b[0]) == 0);
+ assert(a[0] == 4);
+ assert(a[1] == 5);
+ assert(a[2] == 0);
+ assert(b[0] == 5);
+ assert(e == 0);
+ assert(m == NULL);
+}
+
+/* s2 null ptr, handler */
+ATF_TC_WITHOUT_HEAD(s2_null_ptr_handler);
+ATF_TC_BODY(s2_null_ptr_handler, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strcat_s(&a[0], 4, 0) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strcat_s : s2 is NULL"));
+}
+
+/* s1 full already, poor s1, handler */
+ATF_TC_WITHOUT_HEAD(s1_full_already_poor_s1_handler);
+ATF_TC_BODY(s1_full_already_poor_s1_handler, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+ char b[2] = { 5, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strcat_s(&a[0], 4, &b[0]) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strcat_s : s1 is full"));
+}
+
+/* s1 full already, normal case, handler */
+ATF_TC_WITHOUT_HEAD(s1_full_already_normal_case_handler);
+ATF_TC_BODY(s1_full_already_normal_case_handler, tc)
+{
+ char a[4] = { 4, 3, 2, 0 };
+ char b[2] = { 5, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strcat_s(&a[0], 4, &b[0]) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strcat_s : s1 will overflow"));
+}
+
+/* s1 full already, but nothing to cat, handler */
+ATF_TC_WITHOUT_HEAD(s1_full_already_nothing_to_cat_handler);
+ATF_TC_BODY(s1_full_already_nothing_to_cat_handler, tc)
+{
+ char a[4] = { 4, 3, 2, 0 };
+ char b[2] = { 0, 1 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strcat_s(&a[0], 4, &b[0]) == 0);
+ assert(a[0] == 4);
+ assert(a[3] == 0);
+ assert(b[0] == 0);
+ assert(e == 0);
+ assert(m == NULL);
+}
+
+/* s1 will become full, not enough space for null terminator, handler */
+ATF_TC_WITHOUT_HEAD(complex_2);
+ATF_TC_BODY(complex_2, tc)
+{
+ char a[4] = { 4, 3, 0, 1 };
+ char b[3] = { 5, 6, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strcat_s(&a[0], 4, &b[0]) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strcat_s : s1 will overflow"));
+}
+
+/* s1 will become full, simple case, handler */
+ATF_TC_WITHOUT_HEAD(s1_will_become_full_simple_handler);
+ATF_TC_BODY(s1_will_become_full_simple_handler, tc)
+{
+ char a[6] = { 4, 3, 0, 1, 2, 3 };
+ char b[5] = { 5, 6, 7, 8, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strcat_s(&a[0], 6, &b[0]) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strcat_s : s1 will overflow"));
+}
+
+/* s1max == 0, handler */
+ATF_TC_WITHOUT_HEAD(s1max_eq_0_handler);
+ATF_TC_BODY(s1max_eq_0_handler, tc)
+{
+ char a[2] = { 3, 0 };
+ char b[2] = { 5, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strcat_s(&a[0], 0, &b[0]) != 0);
+ assert(a[0] == 3);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strcat_s : s1max == 0"));
+}
+
+/*
+ * s1 will become full,
+ * not enough space for null terminator,
+ * overlapping s1 and s2,
+ * handler
+ */
+ATF_TC_WITHOUT_HEAD(complex_3);
+ATF_TC_BODY(complex_3, tc)
+{
+ char a[4] = { 4, 3, 0, 1 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strcat_s(&a[0], 4, &a[0]) != 0);
+ assert(a[0] == 4);
+ assert(a[1] == 3);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strcat_s : s1 will overflow"));
+}
+
+/* overlapping no zero fill, handler */
+ATF_TC_WITHOUT_HEAD(overlapping_no_zero_fill_handler);
+ATF_TC_BODY(overlapping_no_zero_fill_handler, tc)
+{
+ char a[5] = { 4, 3, 0, 1, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strcat_s(&a[0], 5, &a[0]) != 0);
+ assert(a[0] == 4);
+ assert(a[1] == 3);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strcat_s : memory overlaps"));
+}
+
+/* overlapping zero fill, handler */
+ATF_TC_WITHOUT_HEAD(overlapping_zero_fill_handler);
+ATF_TC_BODY(overlapping_zero_fill_handler, tc)
+{
+ char a[5] = { 4, 3, 0, 1, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strcat_s(&a[0], 5, &a[1]) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strcat_s : memory overlaps"));
+}
+
+/* overlapping, nothing to cat, handler */
+ATF_TC_WITHOUT_HEAD(overlapping_nothing_to_cat_handler);
+ATF_TC_BODY(overlapping_nothing_to_cat_handler, tc)
+{
+ char a[5] = { 4, 3, 0, 1, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strcat_s(&a[0], 5, &a[2]) == 0);
+ assert(a[0] == 4);
+ assert(a[2] == 0);
+ assert(e == 0);
+ assert(m == NULL);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, s1_null_ptr);
+ ATF_TP_ADD_TC(tp, s1max_gt_rmax);
+ ATF_TP_ADD_TC(tp, s1max_lt_0);
+ ATF_TP_ADD_TC(tp, normal);
+ ATF_TP_ADD_TC(tp, s2_null_ptr);
+ ATF_TP_ADD_TC(tp, s1_full_already_poor_s1);
+ ATF_TP_ADD_TC(tp, s1_full_already_normal_case);
+ ATF_TP_ADD_TC(tp, s1_full_already_but_nothing_to_cat);
+ ATF_TP_ADD_TC(tp, trunc_1);
+ ATF_TP_ADD_TC(tp, trunc_2);
+ ATF_TP_ADD_TC(tp, s1max_eq_0);
+ ATF_TP_ADD_TC(tp, complex_1);
+ ATF_TP_ADD_TC(tp, overlapping_no_zero_fill);
+ ATF_TP_ADD_TC(tp, overlapping_zero_fill);
+ ATF_TP_ADD_TC(tp, overlapping_nothing_to_cat);
+ ATF_TP_ADD_TC(tp, s1_null_ptr_handler);
+ ATF_TP_ADD_TC(tp, s1max_gt_rmax_handler);
+ ATF_TP_ADD_TC(tp, s1max_lt_0_handler);
+ ATF_TP_ADD_TC(tp, normal_handler);
+ ATF_TP_ADD_TC(tp, s2_null_ptr_handler);
+ ATF_TP_ADD_TC(tp, s1_full_already_poor_s1_handler);
+ ATF_TP_ADD_TC(tp, s1_full_already_normal_case_handler);
+ ATF_TP_ADD_TC(tp, s1_full_already_nothing_to_cat_handler);
+ ATF_TP_ADD_TC(tp, complex_2);
+ ATF_TP_ADD_TC(tp, s1_will_become_full_simple_handler);
+ ATF_TP_ADD_TC(tp, s1max_eq_0_handler);
+ ATF_TP_ADD_TC(tp, complex_3);
+ ATF_TP_ADD_TC(tp, overlapping_no_zero_fill_handler);
+ ATF_TP_ADD_TC(tp, overlapping_zero_fill_handler);
+ ATF_TP_ADD_TC(tp, overlapping_nothing_to_cat_handler);
+ return (atf_no_error());
+}
Index: lib/libc/tests/string/strcpy_s_test.c
===================================================================
--- /dev/null
+++ lib/libc/tests/string/strcpy_s_test.c
@@ -0,0 +1,382 @@
+/*-
+ * Copyright (c) 2017 Juniper Networks. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <atf-c.h>
+
+static errno_t e;
+static const char * restrict m;
+
+void
+h(const char * restrict msg, void * restrict ptr __unused, errno_t error)
+{
+ e = error;
+ m = msg;
+}
+
+/* s1 null ptr */
+ATF_TC_WITHOUT_HEAD(s1_null_ptr);
+ATF_TC_BODY(s1_null_ptr, tc)
+{
+ char b[2] = { 5, 0 };
+
+ assert(strcpy_s(0, 1, &b[0]) != 0);
+ assert(b[0] = 5);
+}
+
+/* s1max > rmax */
+ATF_TC_WITHOUT_HEAD(s1max_gt_rmax);
+ATF_TC_BODY(s1max_gt_rmax, tc)
+{
+ char a[2] = { 3, 0 };
+ char b[2] = { 5, 0 };
+
+ assert(strcpy_s(&a[0], RSIZE_MAX + 1, &b[0]) != 0);
+ assert(a[0] == 3);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+}
+
+/* s1max < 0 */
+ATF_TC_WITHOUT_HEAD(s1max_lt_0);
+ATF_TC_BODY(s1max_lt_0, tc)
+{
+ char a[2] = { 3, 0 };
+ const char b[2] = { 5, 0 };
+
+ assert(strcpy_s(&a[0], -1, &b[0]) != 0);
+ assert(a[0] == 3);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+}
+
+/* normal */
+ATF_TC_WITHOUT_HEAD(normal);
+ATF_TC_BODY(normal, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+ char b[2] = { 5, 0 };
+
+ assert(strcpy_s(&a[0], 4, &b[0]) == 0);
+ assert(a[0] == 5);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+}
+
+/* s2 null ptr */
+ATF_TC_WITHOUT_HEAD(s2_null_ptr);
+ATF_TC_BODY(s2_null_ptr, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+
+ assert(strcpy_s(&a[0], 4, 0) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+}
+
+/* n > s1max */
+ATF_TC_WITHOUT_HEAD(n_gt_s1max);
+ATF_TC_BODY(n_gt_s1max, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+ char b[6] = { 5, 4, 3, 2, 1, 0 };
+
+ assert(strcpy_s(&a[0], 4, &b[0]) != 0);
+ assert(a[0] == 0);
+ assert(b[0] == 5);
+}
+
+/* n == s1max */
+ATF_TC_WITHOUT_HEAD(n_eq_s1max);
+ATF_TC_BODY(n_eq_s1max, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+ char b[4] = { 5, 4, 3, 0 };
+
+ assert(strcpy_s(&a[0], 4, &b[0]) == 0);
+ assert(a[0] == 5);
+ assert(a[1] == 4);
+ assert(a[2] == 3);
+ assert(a[3] == 0);
+ assert(b[0] == 5);
+}
+
+/* overlap end */
+ATF_TC_WITHOUT_HEAD(overlap_end);
+ATF_TC_BODY(overlap_end, tc)
+{
+ char a[10] = { 4, 3, 2, 1, 1, 2, 3, 4, 0 };
+
+ assert(strcpy_s(&a[0], 5, &a[4]) != 0);
+ assert(a[0] == 0);
+}
+
+/* overlap middle */
+ATF_TC_WITHOUT_HEAD(overlap_middle);
+ATF_TC_BODY(overlap_middle, tc)
+{
+ char a[8] = { 4, 3, 2, 1, 1, 2, 3, 0 };
+
+ assert(strcpy_s(&a[0], 8, &a[2]) != 0);
+ assert(a[0] == 0);
+}
+
+/* overlap beginning */
+ATF_TC_WITHOUT_HEAD(overlap_beginning);
+ATF_TC_BODY(overlap_beginning, tc)
+{
+ char a[7] = { 4, 0, 2, 1, 3, 1, 2 };
+
+ assert(strcpy_s(&a[0], 7, &a[0]) != 0);
+ assert(a[0] == 4);
+}
+
+/* s1 null ptr, handler */
+ATF_TC_WITHOUT_HEAD(s1_null_ptr_handler);
+ATF_TC_BODY(s1_null_ptr_handler, tc)
+{
+ char b[2] = { 5, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strcpy_s(0, 1, &b[0]) != 0);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strcpy_s : s1 is NULL"));
+}
+
+/* s1max > rmax, handler */
+ATF_TC_WITHOUT_HEAD(s1max_gt_rmax_handler);
+ATF_TC_BODY(s1max_gt_rmax_handler, tc)
+{
+ char a[2] = { 3, 0 };
+ char b[2] = { 5, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strcpy_s(&a[0], RSIZE_MAX + 1, &b[0]) != 0);
+ assert(a[0] == 3);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strcpy_s : s1max > RSIZE_MAX"));
+}
+
+/* s1max < 0, handler */
+ATF_TC_WITHOUT_HEAD(s1max_lt_0_handler);
+ATF_TC_BODY(s1max_lt_0_handler, tc)
+{
+ char a[2] = { 3, 0 };
+ const char b[2] = { 5, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strcpy_s(&a[0], -1, &b[0]) != 0);
+ assert(a[0] == 3);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strcpy_s : s1max > RSIZE_MAX"));
+}
+
+/* normal, handler */
+ATF_TC_WITHOUT_HEAD(normal_handler);
+ATF_TC_BODY(normal_handler, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+ const char b[2] = { 5, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strcpy_s(&a[0], 4, &b[0]) == 0);
+ assert(a[0] == 5);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+ assert(e == 0);
+ assert(m == NULL);
+}
+
+/* s2 null ptr, handler */
+ATF_TC_WITHOUT_HEAD(s2_null_ptr_handler);
+ATF_TC_BODY(s2_null_ptr_handler, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strcpy_s(&a[0], 4, 0) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strcpy_s : s2 is NULL"));
+}
+
+/* n > s1max, handler */
+ATF_TC_WITHOUT_HEAD(n_gt_s1max_handler);
+ATF_TC_BODY(n_gt_s1max_handler, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+ char b[6] = { 5, 4, 3, 2, 1, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strcpy_s(&a[0], 4, &b[0]) != 0);
+ assert(a[0] == 0);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strcpy_s : s2 will be truncated"));
+}
+
+/* n == s1max, handler */
+ATF_TC_WITHOUT_HEAD(n_eq_s1max_handler);
+ATF_TC_BODY(n_eq_s1max_handler, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+ const char b[5] = { 5, 4, 3, 2, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strcpy_s(&a[0], 4, &b[0]) != 0);
+ assert(a[0] == 0);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strcpy_s : s2 will be truncated"));
+}
+
+/* overlap end, handler */
+ATF_TC_WITHOUT_HEAD(overlap_end_handler);
+ATF_TC_BODY(overlap_end_handler, tc)
+{
+ char a[10] = { 4, 3, 2, 1, 1, 2, 3, 4, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strcpy_s(&a[0], 5, &a[4]) != 0);
+ assert(a[0] == 0);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strcpy_s : memory overlaps"));
+}
+
+/* overlap middle, handler */
+ATF_TC_WITHOUT_HEAD(overlap_middle_handler);
+ATF_TC_BODY(overlap_middle_handler, tc)
+{
+ char a[8] = { 4, 3, 2, 1, 1, 2, 3, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strcpy_s(&a[0], 8, &a[2]) != 0);
+ assert(a[0] == 0);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strcpy_s : memory overlaps"));
+}
+
+/* overlap beginning, handler */
+ATF_TC_WITHOUT_HEAD(overlap_beginning_handler);
+ATF_TC_BODY(overlap_beginning_handler, tc)
+{
+ char a[7] = { 4, 0, 2, 1, 3, 1, 2 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strcpy_s(&a[0], 7, &a[0]) != 0);
+ assert(a[0] == 4);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strcpy_s : memory overlaps"));
+}
+
+/* s1max == 0, handler */
+ATF_TC_WITHOUT_HEAD(s1max_eq_0_handler);
+ATF_TC_BODY(s1max_eq_0_handler, tc)
+{
+ char a[2] = { 3, 0 };
+ const char b[2] = { 5, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strcpy_s(&a[0], 0, &b[0]) != 0);
+ assert(a[0] == 3);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strcpy_s : s1max == 0"));
+}
+
+/* trival input */
+ATF_TC_WITHOUT_HEAD(trivial_input);
+ATF_TC_BODY(trivial_input, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+ char b[1] = { 0 };
+
+ assert(strcpy_s(&a[0], 4, &b[0]) == 0);
+ assert(a[0] == 0);
+ assert(b[0] == 0);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, s1_null_ptr);
+ ATF_TP_ADD_TC(tp, s1max_gt_rmax);
+ ATF_TP_ADD_TC(tp, s1max_lt_0);
+ ATF_TP_ADD_TC(tp, normal);
+ ATF_TP_ADD_TC(tp, s2_null_ptr);
+ ATF_TP_ADD_TC(tp, n_gt_s1max);
+ ATF_TP_ADD_TC(tp, n_eq_s1max);
+ ATF_TP_ADD_TC(tp, overlap_end);
+ ATF_TP_ADD_TC(tp, overlap_middle);
+ ATF_TP_ADD_TC(tp, overlap_beginning);
+ ATF_TP_ADD_TC(tp, s1_null_ptr_handler);
+ ATF_TP_ADD_TC(tp, s1max_gt_rmax_handler);
+ ATF_TP_ADD_TC(tp, s1max_lt_0_handler);
+ ATF_TP_ADD_TC(tp, normal_handler);
+ ATF_TP_ADD_TC(tp, s2_null_ptr_handler);
+ ATF_TP_ADD_TC(tp, n_gt_s1max_handler);
+ ATF_TP_ADD_TC(tp, n_eq_s1max_handler);
+ ATF_TP_ADD_TC(tp, overlap_end_handler);
+ ATF_TP_ADD_TC(tp, overlap_middle_handler);
+ ATF_TP_ADD_TC(tp, overlap_beginning_handler);
+ ATF_TP_ADD_TC(tp, s1max_eq_0_handler);
+ ATF_TP_ADD_TC(tp, trivial_input);
+ return (atf_no_error());
+}
Index: lib/libc/tests/string/strerror_s_test.c
===================================================================
--- /dev/null
+++ lib/libc/tests/string/strerror_s_test.c
@@ -0,0 +1,297 @@
+/*-
+ * Copyright (c) 2017 Juniper Networks. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <atf-c.h>
+
+static errno_t e;
+static const char * restrict m;
+
+void
+h(const char * restrict msg, void * restrict ptr __unused, errno_t error)
+{
+ e = error;
+ m = msg;
+}
+
+/* s null ptr */
+ATF_TC_WITHOUT_HEAD(s_null_ptr);
+ATF_TC_BODY(s_null_ptr, tc)
+{
+ assert(strerror_s(0, 1, EINVAL) != 0);
+}
+
+/* s null ptr, handler */
+ATF_TC_WITHOUT_HEAD(s_null_ptr_handler);
+ATF_TC_BODY(s_null_ptr_handler, tc)
+{
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strerror_s(0, 1, EINVAL) != 0);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strerror_s : s is NULL"));
+}
+
+/* maxsize > rmax */
+ATF_TC_WITHOUT_HEAD(maxsize_gt_rmax);
+ATF_TC_BODY(maxsize_gt_rmax, tc)
+{
+ char a[2] = { 1, 2 };
+
+ assert(strerror_s(&a[0], RSIZE_MAX + 1, EINVAL) != 0);
+ assert(a[0] == 1);
+ assert(a[1] == 2);
+}
+
+/* maxsize > rmax, handler */
+ATF_TC_WITHOUT_HEAD(maxsize_gt_rmax_handler);
+ATF_TC_BODY(maxsize_gt_rmax_handler, tc)
+{
+ char a[2] = { 1, 2 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strerror_s(&a[0], RSIZE_MAX + 1, EINVAL) != 0);
+ assert(a[0] == 1);
+ assert(a[1] == 2);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strerror_s : maxsize > RSIZE_MAX"));
+}
+
+/* maxsize < 0 */
+ATF_TC_WITHOUT_HEAD(maxsize_lt_0);
+ATF_TC_BODY(maxsize_lt_0, tc)
+{
+ char a[2] = { 1, 2 };
+
+ assert(strerror_s(&a[0], -1, EINVAL) != 0);
+ assert(a[0] == 1);
+ assert(a[1] == 2);
+}
+
+/* maxsize < 0, handler */
+ATF_TC_WITHOUT_HEAD(maxsize_lt_0_handler);
+ATF_TC_BODY(maxsize_lt_0_handler, tc)
+{
+ char a[2] = { 1, 2 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strerror_s(&a[0], -1, EINVAL) != 0);
+ assert(a[0] == 1);
+ assert(a[1] == 2);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strerror_s : maxsize > RSIZE_MAX"));
+}
+
+/* maxsize = 0 */
+ATF_TC_WITHOUT_HEAD(maxsize_eq_0);
+ATF_TC_BODY(maxsize_eq_0, tc)
+{
+ char a[2] = { 1, 2 };
+
+ assert(strerror_s(&a[0], 0, EINVAL) != 0);
+ assert(a[0] == 1);
+ assert(a[1] == 2);
+}
+
+/* maxsize = 0, handler */
+ATF_TC_WITHOUT_HEAD(maxsize_eq_0_handler);
+ATF_TC_BODY(maxsize_eq_0_handler, tc)
+{
+ char a[2] = { 1, 2 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strerror_s(&a[0], 0, EINVAL) != 0);
+ assert(a[0] == 1);
+ assert(a[1] == 2);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strerror_s : maxsize == 0"));
+}
+
+/* short 1 */
+ATF_TC_WITHOUT_HEAD(short_1);
+ATF_TC_BODY(short_1, tc)
+{
+ char a[5] = { 1, 2, 3, 4, 5 };
+
+ assert(strerror_s(&a[0], 1, EINVAL) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 2);
+}
+
+/* short 2 */
+ATF_TC_WITHOUT_HEAD(short_2);
+ATF_TC_BODY(short_2, tc)
+{
+ char a[5] = { 1, 2, 3, 4, 5 };
+
+ assert(strerror_s(&a[0], 2, EINVAL) != 0);
+ assert(a[0] == '.');
+ assert(a[1] == 0);
+ assert(a[2] == 3);
+}
+
+/* short 3 */
+ATF_TC_WITHOUT_HEAD(short_3);
+ATF_TC_BODY(short_3, tc)
+{
+ char a[5] = { 1, 2, 3, 4, 5 };
+
+ assert(strerror_s(&a[0], 3, EINVAL) != 0);
+ assert(a[0] == '.');
+ assert(a[1] == '.');
+ assert(a[2] == 0);
+ assert(a[3] == 4);
+}
+
+/* short 4 */
+ATF_TC_WITHOUT_HEAD(short_4);
+ATF_TC_BODY(short_4, tc)
+{
+ char a[5] = { 1, 2, 3, 4, 5 };
+
+ assert(strerror_s(&a[0], 4, EINVAL) != 0);
+ assert(a[0] == '.');
+ assert(a[1] == '.');
+ assert(a[2] == '.');
+ assert(a[3] == 0);
+ assert(a[4] == 5);
+}
+
+/* normal */
+ATF_TC_WITHOUT_HEAD(normal);
+ATF_TC_BODY(normal, tc)
+{
+ char *a;
+ size_t len;
+
+ len = strerrorlen_s(EINVAL)+1;
+ a = (char *)calloc(len, 1);
+ a[len-1] = 'f';
+ assert(strerror_s(a, len, EINVAL) == 0);
+ assert(a[0] != 0);
+ assert(a[len-1] == 0);
+}
+
+/* normal, handler */
+ATF_TC_WITHOUT_HEAD(normal_handler);
+ATF_TC_BODY(normal_handler, tc)
+{
+ char *a;
+ size_t len;
+
+ len = strerrorlen_s(EINVAL)+1;
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ a = (char *)calloc(len, 1);
+ a[len-1] = 'f';
+ assert(strerror_s(a, len, EINVAL) == 0);
+ assert(a[0] != 0);
+ assert(a[len-1] == 0);
+ assert(e == 0);
+ assert(m == NULL);
+}
+
+/* mid short */
+ATF_TC_WITHOUT_HEAD(mid_short);
+ATF_TC_BODY(mid_short, tc)
+{
+ char *a;
+ size_t len;
+
+ len = strerrorlen_s(EINVAL)+1;
+ if (len > 5) {
+ a = (char *)malloc(len);
+ memset(a, -1, len);
+ assert(strerror_s(a, len-1, EINVAL) != 0);
+ assert(a[0] != -1);
+ assert(a[0] != 0);
+ assert(a[len-1] == -1);
+ assert(a[len-2] == 0);
+ assert(a[len-3] == '.');
+ assert(a[len-4] == '.');
+ assert(a[len-5] == '.');
+ }
+}
+
+/* abusive normal, handler */
+ATF_TC_WITHOUT_HEAD(abusive_normal_handler);
+ATF_TC_BODY(abusive_normal_handler, tc)
+{
+ int i;
+ char *a;
+ size_t len;
+
+ for (i = -1234; i < 1235; i++) {
+ len = strerrorlen_s(i)+1;
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ a = (char *)calloc(len, 1);
+ a[len-1] = 'f';
+ assert(strerror_s(a, len, i) == 0);
+ assert(a[0] != 0);
+ assert(a[len-1] == 0);
+ assert(e == 0);
+ assert(m == NULL);
+ free(a);
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, s_null_ptr);
+ ATF_TP_ADD_TC(tp, s_null_ptr_handler);
+ ATF_TP_ADD_TC(tp, maxsize_gt_rmax);
+ ATF_TP_ADD_TC(tp, maxsize_gt_rmax_handler);
+ ATF_TP_ADD_TC(tp, maxsize_lt_0);
+ ATF_TP_ADD_TC(tp, maxsize_lt_0_handler);
+ ATF_TP_ADD_TC(tp, maxsize_eq_0);
+ ATF_TP_ADD_TC(tp, maxsize_eq_0_handler);
+ ATF_TP_ADD_TC(tp, short_1);
+ ATF_TP_ADD_TC(tp, short_2);
+ ATF_TP_ADD_TC(tp, short_3);
+ ATF_TP_ADD_TC(tp, short_4);
+ ATF_TP_ADD_TC(tp, normal);
+ ATF_TP_ADD_TC(tp, normal_handler);
+ ATF_TP_ADD_TC(tp, mid_short);
+ ATF_TP_ADD_TC(tp, abusive_normal_handler);
+ return (atf_no_error());
+}
Index: lib/libc/tests/string/strncat_s_test.c
===================================================================
--- /dev/null
+++ lib/libc/tests/string/strncat_s_test.c
@@ -0,0 +1,740 @@
+/*-
+ * Copyright (c) 2017 Juniper Networks. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <atf-c.h>
+
+static errno_t e;
+static const char * restrict m;
+
+void
+h(const char * restrict msg, void * restrict ptr __unused, errno_t error)
+{
+ e = error;
+ m = msg;
+}
+
+/* s1 null ptr */
+ATF_TC_WITHOUT_HEAD(s1_null_ptr);
+ATF_TC_BODY(s1_null_ptr, tc)
+{
+ char b[2] = { 5, 0 };
+
+ assert(strncat_s(0, 1, &b[0], 2) != 0);
+ assert(b[0] == 5);
+}
+
+/* s1max > rmax */
+ATF_TC_WITHOUT_HEAD(s1max_gt_rmax);
+ATF_TC_BODY(s1max_gt_rmax, tc)
+{
+ char a[2] = { 3, 0 };
+ char b[2] = { 5, 0 };
+
+ assert(strncat_s(&a[0], RSIZE_MAX + 1, &b[0], 2) != 0);
+ assert(a[0] == 3);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+}
+
+/* s1max < 0 */
+ATF_TC_WITHOUT_HEAD(s1max_lt_0);
+ATF_TC_BODY(s1max_lt_0, tc)
+{
+ char a[2] = { 3, 0 };
+ const char b[2] = { 5, 0 };
+
+ assert(strncat_s(&a[0], -1, &b[0], 2) != 0);
+ assert(a[0] == 3);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+}
+
+/* normal */
+ATF_TC_WITHOUT_HEAD(normal);
+ATF_TC_BODY(normal, tc)
+{
+ char a[4] = { 4, 0, 2, 1 };
+ char b[2] = { 5, 0 };
+
+ assert(strncat_s(&a[0], 4, &b[0], 2) == 0);
+ assert(a[0] == 4);
+ assert(a[1] == 5);
+ assert(a[2] == 0);
+ assert(b[0] == 5);
+}
+
+/* s2 null ptr */
+ATF_TC_WITHOUT_HEAD(s2_null_ptr);
+ATF_TC_BODY(s2_null_ptr, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+
+ assert(strncat_s(&a[0], 4, 0, 1) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+}
+
+/* s1 full already, poor s1 */
+ATF_TC_WITHOUT_HEAD(s1_full_poor_s1);
+ATF_TC_BODY(s1_full_poor_s1, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+ char b[2] = { 5, 0 };
+
+ assert(strncat_s(&a[0], 4, &b[0], 2) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(b[0] == 5);
+}
+
+/* s1 full already, normal case */
+ATF_TC_WITHOUT_HEAD(s1_full_normal_case);
+ATF_TC_BODY(s1_full_normal_case, tc)
+{
+ char a[4] = { 4, 3, 2, 0 };
+ char b[2] = { 5, 0 };
+
+ assert(strncat_s(&a[0], 4, &b[0], 2) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(b[0] == 5);
+}
+
+/* s1 full already, but nothing to cat */
+ATF_TC_WITHOUT_HEAD(s1_full_nothing_to_cat);
+ATF_TC_BODY(s1_full_nothing_to_cat, tc)
+{
+ char a[4] = { 4, 3, 2, 0 };
+ char b[2] = { 0, 1 };
+
+ assert(strncat_s(&a[0], 4, &b[0], 2) == 0);
+ assert(a[0] == 4);
+ assert(a[3] == 0);
+ assert(b[0] == 0);
+}
+
+/* s1 will become full, not enough space for null terminator */
+ATF_TC_WITHOUT_HEAD(s1_full_no_space_for_null);
+ATF_TC_BODY(s1_full_no_space_for_null, tc)
+{
+ char a[4] = { 4, 3, 0, 1 };
+ char b[3] = { 5, 6, 0 };
+
+ assert(strncat_s(&a[0], 4, &b[0], 3) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(b[0] == 5);
+}
+
+/* s1 will become full, simple case */
+ATF_TC_WITHOUT_HEAD(s1_becomes_full_simple);
+ATF_TC_BODY(s1_becomes_full_simple, tc)
+{
+ char a[6] = { 4, 3, 0, 1, 2, 3 };
+ char b[5] = { 5, 6, 7, 8, 0 };
+
+ assert(strncat_s(&a[0], 6, &b[0], 5) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(b[0] == 5);
+}
+
+/* s1max == 0 */
+ATF_TC_WITHOUT_HEAD(s1max_eq_0);
+ATF_TC_BODY(s1max_eq_0, tc)
+{
+ char a[2] = { 3, 0 };
+ char b[2] = { 5, 0 };
+
+ assert(strncat_s(&a[0], 0, &b[0], 2) != 0);
+ assert(a[0] == 3);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+}
+
+/*
+ * s1 will become full,
+ * not enough space for null terminator,
+ * overlapping s1 and s2
+ */
+ATF_TC_WITHOUT_HEAD(complex_1);
+ATF_TC_BODY(complex_1, tc)
+{
+ char a[4] = { 4, 3, 0, 1 };
+
+ assert(strncat_s(&a[0], 4, &a[0], 4) != 0);
+ assert(a[0] == 4);
+ assert(a[1] == 3);
+}
+
+/* overlapping no zero fill */
+ATF_TC_WITHOUT_HEAD(overlapping_no_zero_fill);
+ATF_TC_BODY(overlapping_no_zero_fill, tc)
+{
+ char a[5] = { 4, 3, 0, 1, 0 };
+
+ assert(strncat_s(&a[0], 5, &a[0], 5) != 0);
+ assert(a[0] == 4);
+ assert(a[1] == 3);
+}
+
+/* overlapping zero fill */
+ATF_TC_WITHOUT_HEAD(overlap_zero_fill);
+ATF_TC_BODY(overlap_zero_fill, tc)
+{
+ char a[5] = { 4, 3, 0, 1, 0 };
+
+ assert(strncat_s(&a[0], 5, &a[1], 4) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+}
+
+/* overlapping, nothing to cat */
+ATF_TC_WITHOUT_HEAD(overlapping_nothing_to_cat);
+ATF_TC_BODY(overlapping_nothing_to_cat, tc)
+{
+ char a[5] = { 4, 3, 0, 1, 0 };
+
+ assert(strncat_s(&a[0], 5, &a[2], 3) == 0);
+ assert(a[0] == 4);
+ assert(a[2] == 0);
+}
+
+/* s1 null ptr, handler */
+ATF_TC_WITHOUT_HEAD(s1_null_ptr_handler);
+ATF_TC_BODY(s1_null_ptr_handler, tc)
+{
+ char b[2] = { 5, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncat_s(0, 1, &b[0], 2) != 0);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncat_s : s1 is NULL"));
+}
+
+/* s1max > rmax, handler */
+ATF_TC_WITHOUT_HEAD(s1max_gt_rmax_handler);
+ATF_TC_BODY(s1max_gt_rmax_handler, tc)
+{
+ char a[2] = { 3, 0 };
+ char b[2] = { 5, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncat_s(&a[0], RSIZE_MAX + 1, &b[0], 2) != 0);
+ assert(a[0] == 3);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncat_s : s1max > RSIZE_MAX"));
+}
+
+/* s1max < 0, handler */
+ATF_TC_WITHOUT_HEAD(s1max_lt_0_handler);
+ATF_TC_BODY(s1max_lt_0_handler, tc)
+{
+ char a[2] = { 3, 0 };
+ const char b[2] = {5, 0};
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncat_s(&a[0], -1, &b[0], 2) != 0);
+ assert(a[0] == 3);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncat_s : s1max > RSIZE_MAX"));
+}
+
+/* normal, handler */
+ATF_TC_WITHOUT_HEAD(normal_handler);
+ATF_TC_BODY(normal_handler, tc)
+{
+ char a[4] = { 4, 0, 2, 1 };
+ char b[2] = { 5, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncat_s(&a[0], 4, &b[0], 2) == 0);
+ assert(a[0] == 4);
+ assert(a[1] == 5);
+ assert(a[2] == 0);
+ assert(b[0] == 5);
+ assert(e == 0);
+ assert(m == NULL);
+}
+
+/* s2 null ptr, handler */
+ATF_TC_WITHOUT_HEAD(s2_null_ptr_handler);
+ATF_TC_BODY(s2_null_ptr_handler, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncat_s(&a[0], 4, 0, 1) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncat_s : s2 is NULL"));
+}
+
+/* s1 full already, poor s1, handler */
+ATF_TC_WITHOUT_HEAD(s1_full_poor_s1_handler);
+ATF_TC_BODY(s1_full_poor_s1_handler, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+ char b[2] = { 5, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncat_s(&a[0], 4, &b[0], 2) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncat_s : s1 is full"));
+}
+
+/* s1 full already, normal case, handler */
+ATF_TC_WITHOUT_HEAD(s1_full_normal_handler);
+ATF_TC_BODY(s1_full_normal_handler, tc)
+{
+ char a[4] = { 4, 3, 2, 0 };
+ char b[2] = { 5, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncat_s(&a[0], 4, &b[0], 2) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncat_s : s1 will overflow"));
+}
+
+/* s1 full already, but nothing to cat, handler */
+ATF_TC_WITHOUT_HEAD(s1_full_nothing_to_cat_handler);
+ATF_TC_BODY(s1_full_nothing_to_cat_handler, tc)
+{
+ char a[4] = { 4, 3, 2, 0 };
+ char b[2] = { 0, 1 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncat_s(&a[0], 4, &b[0], 2) == 0);
+ assert(a[0] == 4);
+ assert(a[3] == 0);
+ assert(b[0] == 0);
+ assert(e == 0);
+ assert(m == NULL);
+}
+
+/* s1 will become full, not enough space for null terminator, handler */
+ATF_TC_WITHOUT_HEAD(complex_2);
+ATF_TC_BODY(complex_2, tc)
+{
+ char a[4] = { 4, 3, 0, 1 };
+ char b[3] = { 5, 6, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncat_s(&a[0], 4, &b[0], 3) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncat_s : s1 will overflow"));
+}
+
+/* s1 will become full, simple case, handler */
+ATF_TC_WITHOUT_HEAD(s1_becomes_full_simple_handler);
+ATF_TC_BODY(s1_becomes_full_simple_handler, tc)
+{
+ char a[6] = { 4, 3, 0, 1, 2, 3 };
+ char b[5] = { 5, 6, 7, 8, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncat_s(&a[0], 6, &b[0], 5) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncat_s : s1 will overflow"));
+}
+
+/* s1max == 0, handler */
+ATF_TC_WITHOUT_HEAD(s1max_eq_0_handler);
+ATF_TC_BODY(s1max_eq_0_handler, tc)
+{
+ char a[2] = { 3, 0 };
+ char b[2] = { 5, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncat_s(&a[0], 0, &b[0], 2) != 0);
+ assert(a[0] == 3);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncat_s : s1max == 0"));
+}
+
+/*
+ * s1 will become full,
+ * not enough space for null terminator,
+ * overlapping s1 and s2,
+ * handler
+ */
+ATF_TC_WITHOUT_HEAD(complex_3);
+ATF_TC_BODY(complex_3, tc)
+{
+ char a[4] = { 4, 3, 0, 1 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncat_s(&a[0], 4, &a[0], 4) != 0);
+ assert(a[0] == 4);
+ assert(a[1] == 3);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncat_s : s1 will overflow"));
+}
+
+/* overlapping no zero fill, handler */
+ATF_TC_WITHOUT_HEAD(overlapping_no_zero_fill_handler);
+ATF_TC_BODY(overlapping_no_zero_fill_handler, tc)
+{
+ char a[5] = { 4, 3, 0, 1, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncat_s(&a[0], 5, &a[0], 5) != 0);
+ assert(a[0] == 4);
+ assert(a[1] == 3);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncat_s : memory overlaps"));
+}
+
+/* overlapping zero fill, handler */
+ATF_TC_WITHOUT_HEAD(overlapping_zero_fill_handler);
+ATF_TC_BODY(overlapping_zero_fill_handler, tc)
+{
+ char a[5] = { 4, 3, 0, 1, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncat_s(&a[0], 5, &a[1], 4) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncat_s : memory overlaps"));
+}
+
+/* n > rmax */
+ATF_TC_WITHOUT_HEAD(n_gt_rmax);
+ATF_TC_BODY(n_gt_rmax, tc)
+{
+ char a[2] = { 3, 0 };
+ char b[2] = { 5, 0 };
+
+ assert(strncat_s(&a[0], 2, &b[0], RSIZE_MAX+1) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+}
+
+/* n < 0 */
+ATF_TC_WITHOUT_HEAD(n_lt_0);
+ATF_TC_BODY(n_lt_0, tc)
+{
+ char a[2] = { 3, 0 };
+ const char b[2] = { 5, 0 };
+
+ assert(strncat_s(&a[0], 2, &b[0], -1) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+}
+
+/* n > rmax, handler */
+ATF_TC_WITHOUT_HEAD(n_gt_rmax_handler);
+ATF_TC_BODY(n_gt_rmax_handler, tc)
+{
+ char a[2] = { 3, 0 };
+ char b[2] = { 5, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncat_s(&a[0], 2, &b[0], RSIZE_MAX+1) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncat_s : n > RSIZE_MAX"));
+}
+
+/* n < 0, handler */
+ATF_TC_WITHOUT_HEAD(n_lt_0_handler);
+ATF_TC_BODY(n_lt_0_handler, tc)
+{
+ char a[2] = { 3, 0 };
+ const char b[2] = { 5, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncat_s(&a[0], 2, &b[0], -1) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncat_s : n > RSIZE_MAX"));
+}
+
+/* overlapping, nothing to cat, handler */
+ATF_TC_WITHOUT_HEAD(overlapping_nothing_to_cat_handler);
+ATF_TC_BODY(overlapping_nothing_to_cat_handler, tc)
+{
+ char a[5] = { 4, 3, 0, 1, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncat_s(&a[0], 5, &a[2], 1) == 0);
+ assert(a[0] == 4);
+ assert(a[2] == 0);
+ assert(e == 0);
+ assert(m == NULL);
+}
+
+/* normal, n */
+ATF_TC_WITHOUT_HEAD(normal_n);
+ATF_TC_BODY(normal_n, tc)
+{
+ char a[4] = { 4, 0, 2, 1 };
+ char b[2] = { 5, 0 };
+
+ assert(strncat_s(&a[0], 4, &b[0], 1) == 0);
+ assert(a[0] == 4);
+ assert(a[1] == 5);
+ assert(a[2] == 0);
+ assert(b[0] == 5);
+}
+
+/* s1 full already, normal case, n, handler */
+ATF_TC_WITHOUT_HEAD(s1_full_normal_n_handler);
+ATF_TC_BODY(s1_full_normal_n_handler, tc)
+{
+ char a[4] = { 4, 3, 2, 0 };
+ char b[2] = { 5, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncat_s(&a[0], 4, &b[0], 1) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncat_s : s1 will overflow"));
+}
+
+/* s1 will become full, n, simple case, handler */
+ATF_TC_WITHOUT_HEAD(s1_will_become_full_n_simple_handler);
+ATF_TC_BODY(s1_will_become_full_n_simple_handler, tc)
+{
+ char a[6] = { 4, 3, 0, 1, 2, 3 };
+ char b[5] = { 5, 6, 7, 8, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncat_s(&a[0], 6, &b[0], 4) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncat_s : s1 will overflow"));
+}
+
+/* s1 full already, but nothing to cat, n, handler */
+ATF_TC_WITHOUT_HEAD(s1_full_nothing_to_cat_n_handler);
+ATF_TC_BODY(s1_full_nothing_to_cat_n_handler, tc)
+{
+ char a[4] = { 4, 3, 2, 0 };
+ char b[2] = { 0, 1 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncat_s(&a[0], 4, &b[0], 0) == 0);
+ assert(a[0] == 4);
+ assert(a[3] == 0);
+ assert(b[0] == 0);
+ assert(e == 0);
+ assert(m == NULL);
+}
+
+/* s1 will become full, not enough space for null terminator, n, handler */
+ATF_TC_WITHOUT_HEAD(complex_4);
+ATF_TC_BODY(complex_4, tc)
+{
+ char a[4] = { 4, 3, 0, 1 };
+ char b[3] = { 5, 6, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncat_s(&a[0], 4, &b[0], 2) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncat_s : s1 will overflow"));
+}
+
+/* s1 will become full, simple case, n, handler */
+ATF_TC_WITHOUT_HEAD(s1_will_become_full_simple_n_handler);
+ATF_TC_BODY(s1_will_become_full_simple_n_handler, tc)
+{
+ char a[6] = { 4, 3, 0, 1, 2, 3 };
+ char b[5] = { 5, 6, 7, 8, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncat_s(&a[0], 6, &b[0], 4) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncat_s : s1 will overflow"));
+}
+
+/* overlapping no zero fill, n, handler */
+ATF_TC_WITHOUT_HEAD(overlapping_no_zero_fill_n_handler);
+ATF_TC_BODY(overlapping_no_zero_fill_n_handler, tc)
+{
+ char a[5] = { 4, 3, 0, 1, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncat_s(&a[0], 5, &a[0], 2) != 0);
+ assert(a[0] == 4);
+ assert(a[1] == 3);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncat_s : memory overlaps"));
+}
+
+/* overlapping zero fill, n, handler */
+ATF_TC_WITHOUT_HEAD(overlapping_zero_fill_n_handler);
+ATF_TC_BODY(overlapping_zero_fill_n_handler, tc)
+{
+ char a[5] = { 4, 3, 0, 1, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncat_s(&a[0], 5, &a[1], 1) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncat_s : memory overlaps"));
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, s1_null_ptr);
+ ATF_TP_ADD_TC(tp, s1max_gt_rmax);
+ ATF_TP_ADD_TC(tp, s1max_lt_0);
+ ATF_TP_ADD_TC(tp, normal);
+ ATF_TP_ADD_TC(tp, s2_null_ptr);
+ ATF_TP_ADD_TC(tp, s1_full_poor_s1);
+ ATF_TP_ADD_TC(tp, s1_full_normal_case);
+ ATF_TP_ADD_TC(tp, s1_full_nothing_to_cat);
+ ATF_TP_ADD_TC(tp, s1_full_no_space_for_null);
+ ATF_TP_ADD_TC(tp, s1_becomes_full_simple);
+ ATF_TP_ADD_TC(tp, s1max_eq_0);
+ ATF_TP_ADD_TC(tp, complex_1);
+ ATF_TP_ADD_TC(tp, overlapping_no_zero_fill);
+ ATF_TP_ADD_TC(tp, overlap_zero_fill);
+ ATF_TP_ADD_TC(tp, overlapping_nothing_to_cat);
+ ATF_TP_ADD_TC(tp, s1_null_ptr_handler);
+ ATF_TP_ADD_TC(tp, s1max_gt_rmax_handler);
+ ATF_TP_ADD_TC(tp, s1max_lt_0_handler);
+ ATF_TP_ADD_TC(tp, normal_handler);
+ ATF_TP_ADD_TC(tp, s2_null_ptr_handler);
+ ATF_TP_ADD_TC(tp, s1_full_poor_s1_handler);
+ ATF_TP_ADD_TC(tp, s1_full_normal_handler);
+ ATF_TP_ADD_TC(tp, s1_full_nothing_to_cat_handler);
+ ATF_TP_ADD_TC(tp, complex_2);
+ ATF_TP_ADD_TC(tp, s1_becomes_full_simple_handler);
+ ATF_TP_ADD_TC(tp, s1max_eq_0_handler);
+ ATF_TP_ADD_TC(tp, complex_3);
+ ATF_TP_ADD_TC(tp, overlapping_no_zero_fill_handler);
+ ATF_TP_ADD_TC(tp, overlapping_zero_fill_handler);
+ ATF_TP_ADD_TC(tp, overlapping_nothing_to_cat_handler);
+ ATF_TP_ADD_TC(tp, n_gt_rmax);
+ ATF_TP_ADD_TC(tp, n_lt_0);
+ ATF_TP_ADD_TC(tp, n_gt_rmax_handler);
+ ATF_TP_ADD_TC(tp, n_lt_0_handler);
+ ATF_TP_ADD_TC(tp, normal_n);
+ ATF_TP_ADD_TC(tp, s1_full_normal_n_handler);
+ ATF_TP_ADD_TC(tp, s1_will_become_full_n_simple_handler);
+ ATF_TP_ADD_TC(tp, s1_full_nothing_to_cat_n_handler);
+ ATF_TP_ADD_TC(tp, complex_4);
+ ATF_TP_ADD_TC(tp, s1_will_become_full_simple_n_handler);
+ ATF_TP_ADD_TC(tp, overlapping_no_zero_fill_n_handler);
+ ATF_TP_ADD_TC(tp, overlapping_zero_fill_n_handler);
+ return (atf_no_error());
+}
+
Index: lib/libc/tests/string/strncpy_s_test.c
===================================================================
--- /dev/null
+++ lib/libc/tests/string/strncpy_s_test.c
@@ -0,0 +1,439 @@
+/*-
+ * Copyright (c) 2017 Juniper Networks. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <atf-c.h>
+
+static errno_t e;
+static const char * restrict m;
+
+void
+h(const char * restrict msg, void * restrict ptr __unused, errno_t error)
+{
+ e = error;
+ m = msg;
+}
+
+/* s1 null ptr */
+ATF_TC_WITHOUT_HEAD(s1_null_ptr);
+ATF_TC_BODY(s1_null_ptr, tc)
+{
+ char b[2] = { 5, 0 };
+
+ assert(strncpy_s(0, 1, &b[0], 2) != 0);
+ assert(b[0] == 5);
+}
+
+/* s1max > rmax */
+ATF_TC_WITHOUT_HEAD(s1max_gt_rmax);
+ATF_TC_BODY(s1max_gt_rmax, tc)
+{
+ char a[2] = { 3, 0 };
+ char b[2] = { 5, 0 };
+
+ assert(strncpy_s(&a[0], RSIZE_MAX + 1, &b[0], 2) != 0);
+ assert(a[0] == 3);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+}
+
+/* s1max < 0 */
+ATF_TC_WITHOUT_HEAD(s1max_lt_0);
+ATF_TC_BODY(s1max_lt_0, tc)
+{
+ char a[2] = { 3, 0 };
+ const char b[2] = { 5, 0 };
+
+ assert(strncpy_s(&a[0], -1, &b[0], 2) != 0);
+ assert(a[0] == 3);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+}
+
+/* normal */
+ATF_TC_WITHOUT_HEAD(normal);
+ATF_TC_BODY(normal, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+ char b[2] = { 5, 0 };
+
+ assert(strncpy_s(&a[0], 4, &b[0], 2) == 0);
+ assert(a[0] == 5);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+}
+
+/* s2 null ptr */
+ATF_TC_WITHOUT_HEAD(s2_null_ptr);
+ATF_TC_BODY(s2_null_ptr, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+
+ assert(strncpy_s(&a[0], 4, 0, 0) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+}
+
+/* n > s1max */
+ATF_TC_WITHOUT_HEAD(n_gt_s1max);
+ATF_TC_BODY(n_gt_s1max, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+ char b[6] = { 5, 4, 3, 2, 1, 0 };
+
+ assert(strncpy_s(&a[0], 4, &b[0], 6) != 0);
+ assert(a[0] == 0);
+ assert(b[0] == 5);
+}
+
+/* n == s1max */
+ATF_TC_WITHOUT_HEAD(n_eq_s1max);
+ATF_TC_BODY(n_eq_s1max, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+ char b[4] = { 5, 4, 3, 0 };
+
+ assert(strncpy_s(&a[0], 4, &b[0], 4) == 0);
+ assert(a[0] == 5);
+ assert(a[1] == 4);
+ assert(a[2] == 3);
+ assert(a[3] == 0);
+ assert(b[0] == 5);
+}
+
+/* n == s1max, inferred */
+ATF_TC_WITHOUT_HEAD(n_eq_s1max_inferred);
+ATF_TC_BODY(n_eq_s1max_inferred, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+ char b[6] = { 5, 4, 3, 0, 2, 3 };
+
+ assert(strncpy_s(&a[0], 4, &b[0], 6) == 0);
+ assert(a[0] == 5);
+ assert(a[1] == 4);
+ assert(a[2] == 3);
+ assert(a[3] == 0);
+ assert(b[0] == 5);
+}
+
+/* overlap end */
+ATF_TC_WITHOUT_HEAD(overlap_end);
+ATF_TC_BODY(overlap_end, tc)
+{
+ char a[10] = { 4, 3, 2, 1, 1, 2, 3, 4, 0 };
+
+ assert(strncpy_s(&a[0], 5, &a[4], 6) != 0);
+ assert(a[0] == 0);
+}
+
+/* overlap middle */
+ATF_TC_WITHOUT_HEAD(overlap_middle);
+ATF_TC_BODY(overlap_middle, tc)
+{
+ char a[8] = { 4, 3, 2, 1, 1, 2, 3, 0 };
+
+ assert(strncpy_s(&a[0], 8, &a[2], 6) != 0);
+ assert(a[0] == 0);
+}
+
+/* overlap beginning */
+ATF_TC_WITHOUT_HEAD(overlap_beginning);
+ATF_TC_BODY(overlap_beginning, tc)
+{
+ char a[7] = { 4, 0, 2, 1, 3, 1, 2 };
+
+ assert(strncpy_s(&a[0], 7, &a[0], 7) != 0);
+ assert(a[0] == 4);
+}
+
+/* s1 null ptr, handler */
+ATF_TC_WITHOUT_HEAD(s1_null_ptr_handler);
+ATF_TC_BODY(s1_null_ptr_handler, tc)
+{
+ char b[2] = { 5, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncpy_s(0, 1, &b[0], 2) != 0);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncpy_s : s1 is NULL"));
+}
+
+/* s1max > rmax, handler */
+ATF_TC_WITHOUT_HEAD(s1max_gt_rmax_handler);
+ATF_TC_BODY(s1max_gt_rmax_handler, tc)
+{
+ char a[2] = { 3, 0 };
+ char b[2] = { 5, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncpy_s(&a[0], RSIZE_MAX + 1, &b[0], 2) != 0);
+ assert(a[0] == 3);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncpy_s : s1max > RSIZE_MAX"));
+}
+
+/* s1max < 0, handler */
+ATF_TC_WITHOUT_HEAD(s1max_lt_0_handler);
+ATF_TC_BODY(s1max_lt_0_handler, tc)
+{
+ char a[2] = { 3, 0 };
+ const char b[2] = { 5, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncpy_s(&a[0], -1, &b[0], 2) != 0);
+ assert(a[0] == 3);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncpy_s : s1max > RSIZE_MAX"));
+}
+
+/* normal, handler */
+ATF_TC_WITHOUT_HEAD(normal_handler);
+ATF_TC_BODY(normal_handler, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+ const char b[2] = { 5, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncpy_s(&a[0], 4, &b[0], 2) == 0);
+ assert(a[0] == 5);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+ assert(e == 0);
+ assert(m == NULL);
+}
+
+/* s2 null ptr, handler */
+ATF_TC_WITHOUT_HEAD(s2_null_ptr_handler);
+ATF_TC_BODY(s2_null_ptr_handler, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncpy_s(&a[0], 4, 0, 0) != 0);
+ assert(a[0] == 0);
+ assert(a[1] == 3);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncpy_s : s2 is NULL"));
+}
+
+/* n > s1max, handler */
+ATF_TC_WITHOUT_HEAD(n_gt_s1max_handler);
+ATF_TC_BODY(n_gt_s1max_handler, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+ char b[6] = { 5, 4, 3, 2, 1, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncpy_s(&a[0], 4, &b[0], 6) != 0);
+ assert(a[0] == 0);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncpy_s : s2 will be truncated"));
+}
+
+/* n == s1max, handler */
+ATF_TC_WITHOUT_HEAD(n_eq_s1max_handler);
+ATF_TC_BODY(n_eq_s1max_handler, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+ const char b[5] = { 5, 4, 3, 2, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncpy_s(&a[0], 4, &b[0], 4) != 0);
+ assert(a[0] == 0);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncpy_s : s2 will be truncated"));
+}
+
+/* overlap end, handler */
+ATF_TC_WITHOUT_HEAD(overlap_end_handler);
+ATF_TC_BODY(overlap_end_handler, tc)
+{
+ char a[10] = { 4, 3, 2, 1, 1, 2, 3, 4, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncpy_s(&a[0], 5, &a[4], 6) != 0);
+ assert(a[0] == 0);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncpy_s : memory overlaps"));
+}
+
+/* overlap middle, handler */
+ATF_TC_WITHOUT_HEAD(overlap_middle_handler);
+ATF_TC_BODY(overlap_middle_handler, tc)
+{
+ char a[8] = { 4, 3, 2, 1, 1, 2, 3, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncpy_s(&a[0], 8, &a[2], 6) != 0);
+ assert(a[0] == 0);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncpy_s : memory overlaps"));
+}
+
+/* overlap beginning, handler */
+ATF_TC_WITHOUT_HEAD(overlap_beginning_handler);
+ATF_TC_BODY(overlap_beginning_handler, tc)
+{
+ char a[7] = { 4, 0, 2, 1, 3, 1, 2 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncpy_s(&a[0], 7, &a[0], 7) != 0);
+ assert(a[0] == 4);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncpy_s : memory overlaps"));
+}
+
+/* s1max == 0, handler */
+ATF_TC_WITHOUT_HEAD(s1max_eq_0_handler);
+ATF_TC_BODY(s1max_eq_0_handler, tc)
+{
+ char a[2] = { 3, 0 };
+ const char b[2] = { 5, 0 };
+
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(strncpy_s(&a[0], 0, &b[0], 2) != 0);
+ assert(a[0] == 3);
+ assert(a[1] == 0);
+ assert(b[0] == 5);
+ assert(e != 0);
+ assert(0 == strcmp(m, "strncpy_s : s1max == 0"));
+}
+
+/* trivial input */
+ATF_TC_WITHOUT_HEAD(trivial_input);
+ATF_TC_BODY(trivial_input, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+ char b[1] = { 0 };
+
+ assert(strncpy_s(&a[0], 4, &b[0], 1) == 0);
+ assert(a[0] == 0);
+ assert(b[0] == 0);
+}
+
+/* trivial input, inferred */
+ATF_TC_WITHOUT_HEAD(trivial_input_inferred);
+ATF_TC_BODY(trivial_input_inferred, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+ char b[5] = { 0, 1, 2, 3, 4 };
+
+ assert(strncpy_s(&a[0], 4, &b[0], 5) == 0);
+ assert(a[0] == 0);
+ assert(b[0] == 0);
+}
+
+/* null terminate */
+ATF_TC_WITHOUT_HEAD(null_terminate);
+ATF_TC_BODY(null_terminate, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+ char b[2] = { 1, 2 };
+
+ assert(strncpy_s(&a[0], 4, &b[0], 2) == 0);
+ assert(a[0] == 1);
+ assert(a[1] == 2);
+ assert(a[2] == 0);
+ assert(b[0] == 1);
+}
+
+/* do nothing */
+ATF_TC_WITHOUT_HEAD(do_nothing);
+ATF_TC_BODY(do_nothing, tc)
+{
+ char a[4] = { 4, 3, 2, 1 };
+ char b[2] = { 1, 2 };
+
+ assert(strncpy_s(&a[0], 4, &b[0], 0) == 0);
+ assert(a[0] == 0);
+ assert(b[0] == 1);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, s1_null_ptr);
+ ATF_TP_ADD_TC(tp, s1max_gt_rmax);
+ ATF_TP_ADD_TC(tp, s1max_lt_0);
+ ATF_TP_ADD_TC(tp, normal);
+ ATF_TP_ADD_TC(tp, s2_null_ptr);
+ ATF_TP_ADD_TC(tp, n_gt_s1max);
+ ATF_TP_ADD_TC(tp, n_eq_s1max);
+ ATF_TP_ADD_TC(tp, n_eq_s1max_inferred);
+ ATF_TP_ADD_TC(tp, overlap_end);
+ ATF_TP_ADD_TC(tp, overlap_middle);
+ ATF_TP_ADD_TC(tp, overlap_beginning);
+ ATF_TP_ADD_TC(tp, s1_null_ptr_handler);
+ ATF_TP_ADD_TC(tp, s1max_gt_rmax_handler);
+ ATF_TP_ADD_TC(tp, s1max_lt_0_handler);
+ ATF_TP_ADD_TC(tp, normal_handler);
+ ATF_TP_ADD_TC(tp, s2_null_ptr_handler);
+ ATF_TP_ADD_TC(tp, n_gt_s1max_handler);
+ ATF_TP_ADD_TC(tp, n_eq_s1max_handler);
+ ATF_TP_ADD_TC(tp, overlap_end_handler);
+ ATF_TP_ADD_TC(tp, overlap_middle_handler);
+ ATF_TP_ADD_TC(tp, overlap_beginning_handler);
+ ATF_TP_ADD_TC(tp, s1max_eq_0_handler);
+ ATF_TP_ADD_TC(tp, trivial_input);
+ ATF_TP_ADD_TC(tp, trivial_input_inferred);
+ ATF_TP_ADD_TC(tp, null_terminate);
+ ATF_TP_ADD_TC(tp, do_nothing);
+ return (atf_no_error());
+}
Index: lib/libc/tests/string/strnlen_s_test.c
===================================================================
--- /dev/null
+++ lib/libc/tests/string/strnlen_s_test.c
@@ -0,0 +1,97 @@
+/*-
+ * Copyright (c) 2017 Juniper Networks. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <atf-c.h>
+
+/* s null ptr */
+ATF_TC_WITHOUT_HEAD(s_null_ptr);
+ATF_TC_BODY(s_null_ptr, tc)
+{
+ assert(strnlen_s(0, 1) == 0);
+}
+
+/* 0 maxsize */
+ATF_TC_WITHOUT_HEAD(zero_maxsize);
+ATF_TC_BODY(zero_maxsize, tc)
+{
+ char s[2] = { 48, 0 };
+
+ assert(strnlen_s(&s[0], 0) == 0);
+}
+
+/* short maxsize */
+ATF_TC_WITHOUT_HEAD(short_maxsize);
+ATF_TC_BODY(short_maxsize, tc)
+{
+ char s[4] = { 48, 48, 48, 0 };
+
+ assert(strnlen_s(&s[0], 2) == 2);
+}
+
+/* long maxsize */
+ATF_TC_WITHOUT_HEAD(long_maxsize);
+ATF_TC_BODY(long_maxsize, tc)
+{
+ char s[6] = { 48, 48, 48, 0, 48, 48 };
+
+ assert(strnlen_s(&s[0], 6) == 3);
+}
+
+/* correct maxsize */
+ATF_TC_WITHOUT_HEAD(correct_maxsize);
+ATF_TC_BODY(correct_maxsize, tc)
+{
+ char s[6] = { 48, 48, 48, 0, 48, 48 };
+
+ assert(strnlen_s(&s[0], 3) == 3);
+}
+
+/* correct maxsize with null */
+ATF_TC_WITHOUT_HEAD(correct_maxsize_with_null);
+ATF_TC_BODY(correct_maxsize_with_null, tc)
+{
+ char s[6] = { 48, 48, 48, 0, 48, 48 };
+
+ assert(strnlen_s(&s[0], 4) == 3);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, s_null_ptr);
+ ATF_TP_ADD_TC(tp, zero_maxsize);
+ ATF_TP_ADD_TC(tp, short_maxsize);
+ ATF_TP_ADD_TC(tp, long_maxsize);
+ ATF_TP_ADD_TC(tp, correct_maxsize);
+ ATF_TP_ADD_TC(tp, correct_maxsize_with_null);
+ return (atf_no_error());
+}
Index: lib/libc/tests/string/strtok_s_test.c
===================================================================
--- /dev/null
+++ lib/libc/tests/string/strtok_s_test.c
@@ -0,0 +1,419 @@
+/*-
+ * Copyright (c) 2017 Juniper Networks. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <atf-c.h>
+
+static errno_t e;
+static const char * restrict m;
+
+void
+h(const char * restrict msg, void * restrict ptr __unused, errno_t error)
+{
+ e = error;
+ m = msg;
+}
+
+/* s1 & *ptr null */
+ATF_TC_WITHOUT_HEAD(s1_and_ptr_null);
+ATF_TC_BODY(s1_and_ptr_null, tc)
+{
+ char *ptr;
+ rsize_t s1max;
+
+ ptr = NULL;
+ s1max = 1;
+ assert(NULL == strtok_s(0, &s1max, "", &ptr));
+}
+
+/* s1 & *ptr null, handler */
+ATF_TC_WITHOUT_HEAD(s1_and_ptr_null_handler);
+ATF_TC_BODY(s1_and_ptr_null_handler, tc)
+{
+ char *ptr;
+ rsize_t s1max;
+
+ ptr = NULL;
+ s1max = 1;
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(NULL == strtok_s(0, &s1max, "", &ptr));
+ assert(e != 0);
+ assert(0 == strcmp(m, "strtok_s : *ptr is NULL"));
+}
+
+/* s1max null */
+ATF_TC_WITHOUT_HEAD(s1max_null);
+ATF_TC_BODY(s1max_null, tc)
+{
+ char *ptr;
+
+ ptr = NULL;
+ assert(NULL == strtok_s("", NULL, "", &ptr));
+}
+
+/* s1max null, handler */
+ATF_TC_WITHOUT_HEAD(s1max_null_handler);
+ATF_TC_BODY(s1max_null_handler, tc)
+{
+ char *ptr;
+
+ ptr = NULL;
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(NULL == strtok_s("", NULL, "", &ptr));
+ assert(e != 0);
+ assert(0 == strcmp(m, "strtok_s : s1max is NULL"));
+}
+
+/* s2 null */
+ATF_TC_WITHOUT_HEAD(s2_null);
+ATF_TC_BODY(s2_null, tc)
+{
+ char *ptr;
+ rsize_t s1max;
+
+ ptr = NULL;
+ s1max = 1;
+ assert(NULL == strtok_s("", &s1max, NULL, &ptr));
+}
+
+/* s2 null, handler */
+ATF_TC_WITHOUT_HEAD(s2_null_handler);
+ATF_TC_BODY(s2_null_handler, tc)
+{
+ char *ptr;
+ rsize_t s1max;
+
+ ptr = NULL;
+ s1max = 1;
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(NULL == strtok_s("", &s1max, NULL, &ptr));
+ assert(e != 0);
+ assert(0 == strcmp(m, "strtok_s : s2 is NULL"));
+}
+
+/* ptr null */
+ATF_TC_WITHOUT_HEAD(ptr_null);
+ATF_TC_BODY(ptr_null, tc)
+{
+ rsize_t s1max;
+
+ s1max = 1;
+ assert(NULL == strtok_s("", &s1max, "", NULL));
+}
+
+/* ptr null, handler */
+ATF_TC_WITHOUT_HEAD(ptr_null_handler);
+ATF_TC_BODY(ptr_null_handler, tc)
+{
+ rsize_t s1max;
+
+ s1max = 1;
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(NULL == strtok_s("", &s1max, "", NULL));
+ assert(e != 0);
+ assert(0 == strcmp(m, "strtok_s : ptr is NULL"));
+}
+
+/* s1max > RSIZE_MAX */
+ATF_TC_WITHOUT_HEAD(s1max_gt_rsize_max);
+ATF_TC_BODY(s1max_gt_rsize_max, tc)
+{
+ char *ptr;
+ rsize_t s1max;
+
+ s1max = RSIZE_MAX + 1;
+ assert(NULL == strtok_s("", &s1max, "", &ptr));
+}
+
+/* s1max > RSIZE_MAX, handler */
+ATF_TC_WITHOUT_HEAD(s1max_gt_rsize_max_handler);
+ATF_TC_BODY(s1max_gt_rsize_max_handler, tc)
+{
+ char *ptr;
+ rsize_t s1max;
+
+ s1max = RSIZE_MAX + 1;
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(NULL == strtok_s("", &s1max, "", &ptr));
+ assert(e != 0);
+ assert(0 == strcmp(m, "strtok_s : *s1max > RSIZE_MAX"));
+}
+
+/* s1max < 0 */
+ATF_TC_WITHOUT_HEAD(s1max_lt_0);
+ATF_TC_BODY(s1max_lt_0, tc)
+{
+ char *ptr;
+ rsize_t s1max;
+
+ s1max = -1;
+ assert(NULL == strtok_s("", &s1max, "", &ptr));
+}
+
+/* s1max < 0, handler */
+ATF_TC_WITHOUT_HEAD(s1max_lt_0_handler);
+ATF_TC_BODY(s1max_lt_0_handler, tc)
+{
+ char *ptr;
+ rsize_t s1max;
+
+ s1max = -1;
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(NULL == strtok_s("", &s1max, "", &ptr));
+ assert(e != 0);
+ assert(0 == strcmp(m, "strtok_s : *s1max > RSIZE_MAX"));
+}
+
+
+/* s2 len 0 */
+ATF_TC_WITHOUT_HEAD(s2_len_eq_0);
+ATF_TC_BODY(s2_len_eq_0, tc)
+{
+ char *ptr;
+ rsize_t s1max;
+
+ s1max = 4;
+ assert(NULL == strtok_s("abcd", &s1max, "", &ptr));
+}
+
+/* s2 len 0, handler */
+ATF_TC_WITHOUT_HEAD(s2_len_eq_0_handler);
+ATF_TC_BODY(s2_len_eq_0_handler, tc)
+{
+ char *ptr;
+ rsize_t s1max;
+
+ s1max = 4;
+ e = 0;
+ m = NULL;
+ set_constraint_handler_s(h);
+ assert(NULL == strtok_s("abcd", &s1max, "", &ptr));
+ assert(e == 0);
+ assert(m == NULL);
+}
+
+/* first, failure */
+ATF_TC_WITHOUT_HEAD(first_failure);
+ATF_TC_BODY(first_failure, tc)
+{
+ char *str = " + - + - ";
+ char *dlim = " +-";
+ char *ptr;
+ rsize_t s1max;
+
+ s1max = strlen(str);
+ assert(NULL == strtok_s(str, &s1max, dlim, &ptr));
+ assert(s1max == 0);
+ assert(ptr == NULL);
+}
+
+/* next, failure */
+ATF_TC_WITHOUT_HEAD(next_failure);
+ATF_TC_BODY(next_failure, tc)
+{
+ char *str = " + - + - ";
+ char *dlim = "abc";
+ char *ptr = str;
+ rsize_t s1max;
+
+ s1max = strlen(str);
+ assert(NULL == strtok_s(NULL, &s1max, dlim, &ptr));
+ assert(s1max == 0);
+ assert(ptr == NULL);
+}
+
+/* first, success */
+ATF_TC_WITHOUT_HEAD(first_success);
+ATF_TC_BODY(first_success, tc)
+{
+ char *str = " A - + - ";
+ char *dlim = " +-";
+ char *ptr;
+ char *tok;
+ rsize_t s1max;
+
+ s1max = strlen(str);
+ tok = strtok_s(str, &s1max, dlim, &ptr);
+ assert(tok == &str[1]);
+ assert(tok == ptr);
+ assert(s1max == strlen(tok));
+ assert(str[0] == ' ');
+ assert(str[2] == ' ');
+}
+
+/* first, success 2 */
+ATF_TC_WITHOUT_HEAD(first_success_2);
+ATF_TC_BODY(first_success_2, tc)
+{
+ char *str = "A - + - ";
+ char *dlim = " +-";
+ char *ptr;
+ char *tok;
+ rsize_t s1max;
+
+ s1max = strlen(str);
+ tok = strtok_s(str, &s1max, dlim, &ptr);
+ assert(tok == &str[0]);
+ assert(tok == ptr);
+ assert(s1max == strlen(tok));
+ assert(str[1] == ' ');
+}
+
+/* first, success, stop early */
+ATF_TC_WITHOUT_HEAD(first_success_stop_early);
+ATF_TC_BODY(first_success_stop_early, tc)
+{
+ char *str = " A - + - ";
+ char *dlim = " +-";
+ rsize_t s1max;
+ char *ptr;
+ char *tok;
+
+ s1max = strlen(str) - 2;
+ tok = strtok_s(str, &s1max, dlim, &ptr);
+ assert(tok == &str[1]);
+ assert(tok == ptr);
+ assert(s1max == strlen(tok) - 2);
+ assert(str[0] == ' ');
+ assert(str[2] == ' ');
+}
+
+/* next, success */
+ATF_TC_WITHOUT_HEAD(next_success);
+ATF_TC_BODY(next_success, tc)
+{
+ char *str;
+ char *dlim = " +-";
+ rsize_t s1max;
+ char *ptr;
+ char *tok;
+
+ str = strdup("ABC+DEF");
+ ptr = str;
+ s1max = strlen(str);
+ tok = strtok_s(NULL, &s1max, dlim, &ptr);
+ assert(tok == &str[0]);
+ assert(str[0] == 'A');
+ assert(str[1] == 'B');
+ assert(str[2] == 'C');
+ assert(str[3] == 0);
+ assert(str[4] == 'D');
+ assert(ptr == &str[4]);
+ assert(s1max == 3);
+}
+
+/* next, success, short */
+ATF_TC_WITHOUT_HEAD(next_success_short);
+ATF_TC_BODY(next_success_short, tc)
+{
+ char *str;
+ char *dlim = " +-";
+ rsize_t s1max;
+ char *ptr;
+ char *tok;
+
+ str = strdup("ABC+DEF");
+ ptr = str;
+ s1max = strlen(str) -1;
+ tok = strtok_s(NULL, &s1max, dlim, &ptr);
+ assert(tok == &str[0]);
+ assert(str[0] == 'A');
+ assert(str[1] == 'B');
+ assert(str[2] == 'C');
+ assert(str[3] == 0);
+ assert(str[4] == 'D');
+ assert(ptr == &str[4]);
+ assert(s1max == 2);
+}
+
+/* next, success, short, last */
+ATF_TC_WITHOUT_HEAD(next_success_short_last);
+ATF_TC_BODY(next_success_short_last, tc)
+{
+ char *str;
+ char *dlim = " +-";
+ rsize_t s1max;
+ char *ptr;
+ char *tok;
+
+ str = strdup("ABC+DEF");
+ ptr = str;
+ s1max = strlen(str) -3;
+ tok = strtok_s(NULL, &s1max, dlim, &ptr);
+ assert(tok == &str[0]);
+ assert(str[0] == 'A');
+ assert(str[1] == 'B');
+ assert(str[2] == 'C');
+ assert(str[3] == 0);
+ assert(str[4] == 'D');
+ assert(ptr == NULL);
+ assert(s1max == 0);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, s1_and_ptr_null);
+ ATF_TP_ADD_TC(tp, s1_and_ptr_null_handler);
+ ATF_TP_ADD_TC(tp, s1max_null);
+ ATF_TP_ADD_TC(tp, s1max_null_handler);
+ ATF_TP_ADD_TC(tp, s2_null);
+ ATF_TP_ADD_TC(tp, s2_null_handler);
+ ATF_TP_ADD_TC(tp, ptr_null);
+ ATF_TP_ADD_TC(tp, ptr_null_handler);
+ ATF_TP_ADD_TC(tp, s1max_gt_rsize_max);
+ ATF_TP_ADD_TC(tp, s1max_gt_rsize_max_handler);
+ ATF_TP_ADD_TC(tp, s1max_lt_0);
+ ATF_TP_ADD_TC(tp, s1max_lt_0_handler);
+ ATF_TP_ADD_TC(tp, s2_len_eq_0);
+ ATF_TP_ADD_TC(tp, s2_len_eq_0_handler);
+ ATF_TP_ADD_TC(tp, first_failure);
+ ATF_TP_ADD_TC(tp, next_failure);
+ ATF_TP_ADD_TC(tp, first_success);
+ ATF_TP_ADD_TC(tp, first_success_2);
+ ATF_TP_ADD_TC(tp, first_success_stop_early);
+ ATF_TP_ADD_TC(tp, next_success);
+ ATF_TP_ADD_TC(tp, next_success_short);
+ ATF_TP_ADD_TC(tp, next_success_short_last);
+ return (atf_no_error());
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Oct 19, 4:45 PM (2 h, 18 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
23933049
Default Alt Text
D10469.diff (120 KB)
Attached To
Mode
D10469: The c11 appendix K string functions
Attached
Detach File
Event Timeline
Log In to Comment