Index: include/stddef.h =================================================================== --- include/stddef.h +++ include/stddef.h @@ -72,4 +72,9 @@ #define offsetof(type, member) __offsetof(type, member) +#ifdef __STDC_LIB_EXT1__ +/* ISO/IEC 9899:2011 K.3.3.2 */ +typedef size_t rsize_t; +#endif + #endif /* _STDDEF_H_ */ Index: include/string.h =================================================================== --- include/string.h +++ include/string.h @@ -141,6 +141,12 @@ #if __POSIX_VISIBLE >= 200809 || defined(_XLOCALE_H_) #include #endif + +#ifdef __STDC_LIB_EXT1__ +/* ISO/IEC 9899:2011 K.3.7.4.1.1 */ +errno_t memset_s(void *s, rsize_t smax, int c, rsize_t n); +#endif + __END_DECLS #endif /* _STRING_H_ */ Index: lib/libc/string/Makefile.inc =================================================================== --- lib/libc/string/Makefile.inc +++ lib/libc/string/Makefile.inc @@ -10,7 +10,7 @@ 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 \ + 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 \ Index: lib/libc/string/Symbol.map =================================================================== --- lib/libc/string/Symbol.map +++ lib/libc/string/Symbol.map @@ -107,6 +107,7 @@ FBSD_1.5 { timingsafe_bcmp; timingsafe_memcmp; + memset_s; }; FBSDprivate_1.0 { Index: lib/libc/string/memset_s.c =================================================================== --- /dev/null +++ lib/libc/string/memset_s.c @@ -0,0 +1,49 @@ +/* + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * 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. + */ + +#define __STDC_LIB_EXT1__ +#include +#include +#include +#include + +/* ISO/IEC 9899:2011 K.3.7.4.1 */ +errno_t memset_s(void *s, rsize_t smax, int c, rsize_t n) { + errno_t ret = EINVAL; + if ((s != NULL) && (smax <= RSIZE_MAX) && (n <= RSIZE_MAX)) { + rsize_t lim = smax; + unsigned char v = (unsigned char)c; + volatile unsigned char *dst = (unsigned char *)s; + if (n < smax) + lim = n; + while (lim > 0) + dst[--lim] = v; + ret = 0; + } + return ret; +} Index: lib/libc/tests/string/Makefile =================================================================== --- lib/libc/tests/string/Makefile +++ lib/libc/tests/string/Makefile @@ -1,6 +1,7 @@ # $FreeBSD$ ATF_TESTS_C+= memcmp_test +ATF_TESTS_C+= memset_s_test ATF_TESTS_C+= stpncpy_test ATF_TESTS_C+= strerror2_test ATF_TESTS_C+= wcscasecmp_test Index: lib/libc/tests/string/memset_s_test.c =================================================================== --- /dev/null +++ lib/libc/tests/string/memset_s_test.c @@ -0,0 +1,120 @@ +/* + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * 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. + */ + +#define __STDC_LIB_EXT1__ +#include +#include +#include +#include + +#include +#include + +/* null ptr */ +ATF_TC_WITHOUT_HEAD(null_ptr); +ATF_TC_BODY(null_ptr, tc) +{ + assert(0 != memset_s(0, 1, 1, 1)); +} + +/* smax > rmax */ +ATF_TC_WITHOUT_HEAD(smax_gt_rmax); +ATF_TC_BODY(smax_gt_rmax, tc) +{ + char b; + assert(0 != memset_s(&b, RSIZE_MAX + 1, 1, 1)); +} + +/* smax < 0 */ +ATF_TC_WITHOUT_HEAD(smax_lt_zero); +ATF_TC_BODY(smax_lt_zero, tc) +{ + char b; + assert(0 != memset_s(&b, -1, 1, 1)); +} + +/* normal */ +ATF_TC_WITHOUT_HEAD(normal); +ATF_TC_BODY(normal, tc) +{ + char b = 3; + assert(0 == memset_s(&b, 1, 5, 1)); + assert(b == 5); +} + +/* n > rmax */ +ATF_TC_WITHOUT_HEAD(n_gt_rmax); +ATF_TC_BODY(n_gt_rmax, tc) +{ + char b; + assert(0 != memset_s(&b, 1, 1, RSIZE_MAX + 1)); +} + +/* n < 0 */ +ATF_TC_WITHOUT_HEAD(n_lt_zero); +ATF_TC_BODY(n_lt_zero, tc) +{ + char b; + assert(0 != memset_s(&b, 1, 1, -1)); +} + +/* n < smax */ +ATF_TC_WITHOUT_HEAD(n_lt_smax); +ATF_TC_BODY(n_lt_smax, tc) +{ + char b[3] = {1, 2, 3}; + assert(0 == memset_s(&b[0], 3, 9, 1)); + assert(b[0] == 9); + assert(b[1] == 2); + assert(b[2] == 3); +} + +/* n > smax */ +ATF_TC_WITHOUT_HEAD(n_gt_smax); +ATF_TC_BODY(n_gt_smax, tc) +{ + char b[3] = {1, 2, 3}; + assert(0 == memset_s(&b[0], 1, 9, 3)); + assert(b[0] == 9); + assert(b[1] == 2); + assert(b[2] == 3); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, null_ptr); + ATF_TP_ADD_TC(tp, smax_gt_rmax); + ATF_TP_ADD_TC(tp, smax_lt_zero); + ATF_TP_ADD_TC(tp, normal); + ATF_TP_ADD_TC(tp, n_gt_rmax); + ATF_TP_ADD_TC(tp, n_lt_zero); + ATF_TP_ADD_TC(tp, n_gt_smax); + ATF_TP_ADD_TC(tp, n_lt_smax); + return (atf_no_error()); +} + Index: sys/sys/errno.h =================================================================== --- sys/sys/errno.h +++ sys/sys/errno.h @@ -193,4 +193,9 @@ #define ERELOOKUP (-5) /* retry the directory lookup */ #endif +#ifdef __STDC_LIB_EXT1__ +/* ISO/IEC 9899:2011 K.3.2.2 */ +typedef int errno_t; +#endif + #endif Index: sys/sys/stdint.h =================================================================== --- sys/sys/stdint.h +++ sys/sys/stdint.h @@ -66,4 +66,11 @@ #define WCHAR_MIN __WCHAR_MIN #define WCHAR_MAX __WCHAR_MAX +#ifdef __STDC_LIB_EXT1__ +/* ISO/IEC 9899:2011 K.3.4.4 */ +#ifndef RSIZE_MAX +#define RSIZE_MAX (SIZE_MAX >> 1) +#endif +#endif + #endif /* !_SYS_STDINT_H_ */