Index: head/lib/libc/stdlib/set_constraint_handler_s.c =================================================================== --- head/lib/libc/stdlib/set_constraint_handler_s.c (revision 322426) +++ head/lib/libc/stdlib/set_constraint_handler_s.c (revision 322427) @@ -1,95 +1,101 @@ /*- * 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 __FBSDID("$FreeBSD$"); #include "namespace.h" #include #include #include #include #include #include +#include +#include #include "un-namespace.h" #include "libc_private.h" /* * Rationale recommends allocating new memory each time. */ static constraint_handler_t *_ch = NULL; static pthread_mutex_t ch_lock = PTHREAD_MUTEX_INITIALIZER; constraint_handler_t set_constraint_handler_s(constraint_handler_t handler) { constraint_handler_t *new, *old, ret; new = malloc(sizeof(constraint_handler_t)); if (new == NULL) return (NULL); *new = handler; if (__isthreaded) _pthread_mutex_lock(&ch_lock); old = _ch; _ch = new; if (__isthreaded) _pthread_mutex_unlock(&ch_lock); if (old == NULL) { ret = NULL; } else { ret = *old; free(old); } return (ret); } void __throw_constraint_handler_s(const char * restrict msg, errno_t error) { constraint_handler_t ch; if (__isthreaded) _pthread_mutex_lock(&ch_lock); ch = _ch != NULL ? *_ch : NULL; if (__isthreaded) _pthread_mutex_unlock(&ch_lock); if (ch != NULL) ch(msg, NULL, error); } void -abort_handler_s(const char * restrict msg __unused, - void * restrict ptr __unused, errno_t error __unused) +abort_handler_s(const char * restrict msg, void * restrict ptr __unused, + errno_t error __unused) { + static const char ahs[] = "abort_handler_s : "; + (void) _write(STDERR_FILENO, ahs, sizeof(ahs) - 1); + (void) _write(STDERR_FILENO, msg, strlen(msg)); + (void) _write(STDERR_FILENO, "\n", 1); abort(); } void ignore_handler_s(const char * restrict msg __unused, void * restrict ptr __unused, errno_t error __unused) { } Index: head/lib/libc/string/memset_s.c =================================================================== --- head/lib/libc/string/memset_s.c (revision 322426) +++ head/lib/libc/string/memset_s.c (revision 322427) @@ -1,63 +1,66 @@ /*- * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include "libc_private.h" /* 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; rsize_t lim; unsigned char v; volatile unsigned char *dst; ret = EINVAL; - lim = smax; + lim = n < smax ? n : smax; v = (unsigned char)c; dst = (unsigned char *)s; if (s == NULL) { __throw_constraint_handler_s("memset_s : s is NULL", ret); } else if (smax > RSIZE_MAX) { __throw_constraint_handler_s("memset_s : smax > RSIZE_MAX", ret); } else if (n > RSIZE_MAX) { __throw_constraint_handler_s("memset_s : n > RSIZE_MAX", ret); } else { - if (n < smax) - lim = n; while (lim > 0) dst[--lim] = v; - ret = 0; + if (n > smax) { + __throw_constraint_handler_s("memset_s : n > smax", + ret); + } else { + ret = 0; + } } return (ret); } Index: head/lib/libc/tests/string/memset_s_test.c =================================================================== --- head/lib/libc/tests/string/memset_s_test.c (revision 322426) +++ head/lib/libc/tests/string/memset_s_test.c (revision 322427) @@ -1,195 +1,200 @@ /*- * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include 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; } /* null ptr */ ATF_TC_WITHOUT_HEAD(null_ptr); ATF_TC_BODY(null_ptr, tc) { assert(memset_s(0, 1, 1, 1) != 0); } /* smax > rmax */ ATF_TC_WITHOUT_HEAD(smax_gt_rmax); ATF_TC_BODY(smax_gt_rmax, tc) { char b; assert(memset_s(&b, RSIZE_MAX + 1, 1, 1) != 0); } /* smax < 0 */ ATF_TC_WITHOUT_HEAD(smax_lt_zero); ATF_TC_BODY(smax_lt_zero, tc) { char b; assert(memset_s(&b, -1, 1, 1) != 0); } /* normal */ ATF_TC_WITHOUT_HEAD(normal); ATF_TC_BODY(normal, tc) { char b; b = 3; assert(memset_s(&b, 1, 5, 1) == 0); assert(b == 5); } /* n > rmax */ ATF_TC_WITHOUT_HEAD(n_gt_rmax); ATF_TC_BODY(n_gt_rmax, tc) { char b; assert(memset_s(&b, 1, 1, RSIZE_MAX + 1) != 0); } /* n < 0 */ ATF_TC_WITHOUT_HEAD(n_lt_zero); ATF_TC_BODY(n_lt_zero, tc) { char b; assert(memset_s(&b, 1, 1, -1) != 0); } /* n < smax */ ATF_TC_WITHOUT_HEAD(n_lt_smax); ATF_TC_BODY(n_lt_smax, tc) { char b[3] = {1, 2, 3}; assert(memset_s(&b[0], 3, 9, 1) == 0); assert(b[0] == 9); assert(b[1] == 2); assert(b[2] == 3); } -/* n > smax */ +/* n > smax, handler */ ATF_TC_WITHOUT_HEAD(n_gt_smax); ATF_TC_BODY(n_gt_smax, tc) { char b[3] = {1, 2, 3}; - assert(memset_s(&b[0], 1, 9, 3) == 0); + e = 0; + m = NULL; + set_constraint_handler_s(h); + assert(memset_s(&b[0], 1, 9, 3) != 0); + assert(e > 0); + assert(strcmp(m, "memset_s : n > smax") == 0); assert(b[0] == 9); assert(b[1] == 2); assert(b[2] == 3); } /* smax > rmax, handler */ ATF_TC_WITHOUT_HEAD(smax_gt_rmax_handler); ATF_TC_BODY(smax_gt_rmax_handler, tc) { char b; e = 0; m = NULL; set_constraint_handler_s(h); assert(memset_s(&b, RSIZE_MAX + 1, 1, 1) != 0); assert(e > 0); assert(strcmp(m, "memset_s : smax > RSIZE_MAX") == 0); } /* smax < 0, handler */ ATF_TC_WITHOUT_HEAD(smax_lt_zero_handler); ATF_TC_BODY(smax_lt_zero_handler, tc) { char b; e = 0; m = NULL; set_constraint_handler_s(h); assert(memset_s(&b, -1, 1, 1) != 0); assert(e > 0); assert(strcmp(m, "memset_s : smax > RSIZE_MAX") == 0); } /* n > rmax, handler */ ATF_TC_WITHOUT_HEAD(n_gt_rmax_handler); ATF_TC_BODY(n_gt_rmax_handler, tc) { char b; e = 0; m = NULL; set_constraint_handler_s(h); assert(memset_s(&b, 1, 1, RSIZE_MAX + 1) != 0); assert(e > 0); assert(strcmp(m, "memset_s : n > RSIZE_MAX") == 0); } /* n < 0, handler */ ATF_TC_WITHOUT_HEAD(n_lt_zero_handler); ATF_TC_BODY(n_lt_zero_handler, tc) { char b; e = 0; m = NULL; set_constraint_handler_s(h); assert(memset_s(&b, 1, 1, -1) != 0); assert(e > 0); assert(strcmp(m, "memset_s : n > RSIZE_MAX") == 0); } 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); ATF_TP_ADD_TC(tp, smax_gt_rmax_handler); ATF_TP_ADD_TC(tp, smax_lt_zero_handler); ATF_TP_ADD_TC(tp, n_gt_rmax_handler); ATF_TP_ADD_TC(tp, n_lt_zero_handler); return (atf_no_error()); }