Page MenuHomeFreeBSD

D10469.diff
No OneTemporary

D10469.diff

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

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)

Event Timeline