summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/head/iso/stddef_iso.h13
-rw-r--r--usr/src/head/iso/stdlib_c11.h20
-rw-r--r--usr/src/head/iso/string_iso.h16
-rw-r--r--usr/src/head/stdint.h7
-rw-r--r--usr/src/lib/libc/amd64/Makefile2
-rw-r--r--usr/src/lib/libc/i386/Makefile.com2
-rw-r--r--usr/src/lib/libc/inc/libc.h10
-rw-r--r--usr/src/lib/libc/port/gen/memset_s.c76
-rw-r--r--usr/src/lib/libc/port/gen/set_constraint_handler_s.c107
-rw-r--r--usr/src/lib/libc/port/mapfile-vers8
-rw-r--r--usr/src/lib/libc/port/threads/assfail.c2
-rw-r--r--usr/src/lib/libc/sparc/Makefile.com2
-rw-r--r--usr/src/lib/libc/sparcv9/Makefile.com2
-rw-r--r--usr/src/man/man3c/Makefile9
-rw-r--r--usr/src/man/man3c/memset_s.3c104
-rw-r--r--usr/src/man/man3c/set_constraint_handler_s.3c133
-rw-r--r--usr/src/pkg/manifests/system-library.man3c.inc6
-rw-r--r--usr/src/pkg/manifests/system-test-libctest.mf4
-rw-r--r--usr/src/test/libc-tests/runfiles/default.run12
-rw-r--r--usr/src/test/libc-tests/tests/Makefile7
-rw-r--r--usr/src/test/libc-tests/tests/memset_s.c126
-rw-r--r--usr/src/test/libc-tests/tests/set_constraint_handler_s.c44
-rw-r--r--usr/src/uts/common/sys/feature_tests.h29
23 files changed, 731 insertions, 10 deletions
diff --git a/usr/src/head/iso/stddef_iso.h b/usr/src/head/iso/stddef_iso.h
index 32b34c7be3..f42c1041d8 100644
--- a/usr/src/head/iso/stddef_iso.h
+++ b/usr/src/head/iso/stddef_iso.h
@@ -89,6 +89,19 @@ typedef _MAX_ALIGNMENT_TYPE max_align_t;
#endif /* !_STRICT_SYMBOLS || _STDC_C11 */
#endif /* _MAX_ALIGN_T */
+#if __EXT1_VISIBLE
+/* ISO/IEC 9899:2011 K.3.3.2 */
+#ifndef _RSIZE_T_DEFINED
+#define _RSIZE_T_DEFINED
+typedef size_t rsize_t;
+#endif
+/* ISO/IEC 9899:2011 K.3.2.2 */
+#ifndef _ERRNO_T_DEFINED
+#define _ERRNO_T_DEFINED
+typedef int errno_t;
+#endif
+#endif /* __EXT1_VISIBLE */
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/head/iso/stdlib_c11.h b/usr/src/head/iso/stdlib_c11.h
index b02ef2d884..5648ca4083 100644
--- a/usr/src/head/iso/stdlib_c11.h
+++ b/usr/src/head/iso/stdlib_c11.h
@@ -65,6 +65,26 @@ extern int at_quick_exit(void (*)(void));
extern _NORETURN_KYWD void quick_exit(int);
#endif /* !_STRICT_SYMBOLS || _STDC_C11 || __cplusplus >= 201103L */
+#if __EXT1_VISIBLE
+
+#ifndef _ERRNO_T_DEFINED
+#define _ERRNO_T_DEFINED
+typedef int errno_t;
+#endif
+
+/* K.3.6 */
+typedef void (*constraint_handler_t)(const char *_RESTRICT_KYWD,
+ void *_RESTRICT_KYWD, errno_t);
+/* K.3.6.1.1 */
+extern constraint_handler_t set_constraint_handler_s(constraint_handler_t);
+/* K.3.6.1.2 */
+extern _NORETURN_KYWD void abort_handler_s(const char *_RESTRICT_KYWD,
+ void *_RESTRICT_KYWD, errno_t);
+/* K3.6.1.3 */
+extern void ignore_handler_s(const char *_RESTRICT_KYWD, void *_RESTRICT_KYWD,
+ errno_t);
+#endif /* __EXT1_VISIBLE */
+
#if __cplusplus >= 199711L
}
#endif
diff --git a/usr/src/head/iso/string_iso.h b/usr/src/head/iso/string_iso.h
index 38878e30e2..d493e13008 100644
--- a/usr/src/head/iso/string_iso.h
+++ b/usr/src/head/iso/string_iso.h
@@ -143,6 +143,22 @@ extern char *strrchr(const char *, int);
extern char *strstr(const char *, const char *);
#endif /* __cplusplus >= 199711L */
+#if __EXT1_VISIBLE
+
+#ifndef _RSIZE_T_DEFINED
+#define _RSIZE_T_DEFINED
+typedef size_t rsize_t;
+#endif
+
+#ifndef _ERRNO_T_DEFINED
+#define _ERRNO_T_DEFINED
+typedef int errno_t;
+#endif
+
+/* ISO/IEC 9899:2011 K.3.7.4.1.1 */
+extern errno_t memset_s(void *, rsize_t, int, rsize_t);
+#endif /* __EXT1_VISIBLE */
+
#if __cplusplus >= 199711L
}
#endif /* end of namespace std */
diff --git a/usr/src/head/stdint.h b/usr/src/head/stdint.h
index 135d0bc2fb..cb1bc88510 100644
--- a/usr/src/head/stdint.h
+++ b/usr/src/head/stdint.h
@@ -35,4 +35,11 @@
#include <sys/stdint.h>
+#if __EXT1_VISIBLE
+/* ISO/IEC 9899:2011 K.3.4.4 */
+#ifndef RSIZE_MAX
+#define RSIZE_MAX (SIZE_MAX >> 1)
+#endif
+#endif /* __EXT1_VISIBLE */
+
#endif /* _STDINT_H */
diff --git a/usr/src/lib/libc/amd64/Makefile b/usr/src/lib/libc/amd64/Makefile
index c4e99d26f3..266a12f48b 100644
--- a/usr/src/lib/libc/amd64/Makefile
+++ b/usr/src/lib/libc/amd64/Makefile
@@ -467,6 +467,7 @@ PORTGEN= \
malloc.o \
memalign.o \
memmem.o \
+ memset_s.o \
mkdev.o \
mkdtemp.o \
mkfifo.o \
@@ -524,6 +525,7 @@ PORTGEN= \
scandir.o \
seekdir.o \
select.o \
+ set_constraint_handler_s.o \
setlabel.o \
setpriority.o \
settimeofday.o \
diff --git a/usr/src/lib/libc/i386/Makefile.com b/usr/src/lib/libc/i386/Makefile.com
index 244f5e6470..38e69d0769 100644
--- a/usr/src/lib/libc/i386/Makefile.com
+++ b/usr/src/lib/libc/i386/Makefile.com
@@ -504,6 +504,7 @@ PORTGEN= \
malloc.o \
memalign.o \
memmem.o \
+ memset_s.o \
mkdev.o \
mkdtemp.o \
mkfifo.o \
@@ -561,6 +562,7 @@ PORTGEN= \
scandir.o \
seekdir.o \
select.o \
+ set_constraint_handler_s.o \
setlabel.o \
setpriority.o \
settimeofday.o \
diff --git a/usr/src/lib/libc/inc/libc.h b/usr/src/lib/libc/inc/libc.h
index 86d894b3de..3d440ab2e2 100644
--- a/usr/src/lib/libc/inc/libc.h
+++ b/usr/src/lib/libc/inc/libc.h
@@ -316,6 +316,16 @@ extern wint_t __ungetwc_xpg5(wint_t, FILE *);
*/
extern char *current_locale(locale_t, int);
+/*
+ * defined in set_constraint_handler_s.c.
+ */
+extern void __throw_constraint_handler_s(const char *_RESTRICT_KYWD, int);
+
+/*
+ * defined in assfail.c.
+ */
+extern void common_panic(const char *, const char *);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/libc/port/gen/memset_s.c b/usr/src/lib/libc/port/gen/memset_s.c
new file mode 100644
index 0000000000..9f3fcf8ec0
--- /dev/null
+++ b/usr/src/lib/libc/port/gen/memset_s.c
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+/*
+ * Copyright 2018 Nexenta Systems, Inc.
+ */
+
+#include "lint.h"
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "libc.h"
+
+/* __memset_vp is a volatile pointer to memset() function */
+static void *(*const volatile __memset_vp)(void *, int, size_t) = (memset);
+
+/* 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;
+
+ ret = EINVAL;
+ lim = n < smax ? n : smax;
+ v = (unsigned char)c;
+ 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 {
+ /*
+ * Both s and smax are valid, fill the memory buffer using
+ * memset() called through a volatile pointer to guarantee
+ * it will not be optimized away.
+ */
+ (*__memset_vp)(s, v, lim);
+
+ if (n > RSIZE_MAX) {
+ __throw_constraint_handler_s("memset_s: n > RSIZE_MAX",
+ ret);
+ } else if (n > smax) {
+ __throw_constraint_handler_s("memset_s: n > smax", ret);
+ } else {
+ ret = 0;
+ }
+ }
+ return (ret);
+}
diff --git a/usr/src/lib/libc/port/gen/set_constraint_handler_s.c b/usr/src/lib/libc/port/gen/set_constraint_handler_s.c
new file mode 100644
index 0000000000..3466b8a1d0
--- /dev/null
+++ b/usr/src/lib/libc/port/gen/set_constraint_handler_s.c
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+/*
+ * Copyright 2018 Nexenta Systems, Inc.
+ */
+
+#include "lint.h"
+
+#include <sys/types.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <synch.h>
+#include <thread.h>
+#include <unistd.h>
+
+#include "libc.h"
+
+/*
+ * Rationale recommends allocating new memory each time.
+ */
+static constraint_handler_t *_ch = NULL;
+static mutex_t ch_lock = ERRORCHECKMUTEX;
+
+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;
+ mutex_enter(&ch_lock);
+ old = _ch;
+ _ch = new;
+ mutex_exit(&ch_lock);
+ if (old == NULL) {
+ ret = NULL;
+ } else {
+ ret = *old;
+ free(old);
+ }
+ return (ret);
+}
+
+/*ARGSUSED*/
+void
+abort_handler_s(const char *_RESTRICT_KYWD msg,
+ void *_RESTRICT_KYWD ptr, errno_t error)
+{
+ common_panic("abort_handler_s: ", msg);
+}
+
+/*ARGSUSED*/
+void
+ignore_handler_s(const char *_RESTRICT_KYWD msg,
+ void *_RESTRICT_KYWD ptr, errno_t error)
+{
+}
+
+void
+__throw_constraint_handler_s(const char *_RESTRICT_KYWD msg, errno_t error)
+{
+ constraint_handler_t ch;
+
+ mutex_enter(&ch_lock);
+ ch = (_ch != NULL) ? *_ch : NULL;
+ mutex_exit(&ch_lock);
+ if (ch != NULL) {
+ ch(msg, NULL, error);
+ } else {
+ /*
+ * If current handler is NULL (there were no calls to
+ * set_constraint_handler_s(), or it was called with NULL
+ * pointer handler argument), call default constraint handler
+ * per K.3.6.1.1 points 4 and 5.
+ *
+ * This implementation defines abort_handler_s() as default.
+ */
+ abort_handler_s(msg, NULL, error);
+ }
+}
diff --git a/usr/src/lib/libc/port/mapfile-vers b/usr/src/lib/libc/port/mapfile-vers
index 6d7507c254..c2db2cf62c 100644
--- a/usr/src/lib/libc/port/mapfile-vers
+++ b/usr/src/lib/libc/port/mapfile-vers
@@ -77,6 +77,14 @@ $if _x86 && _ELF64
$add amd64
$endif
+SYMBOL_VERSION ILLUMOS_0.27 { # memset_s(3C) and set_constraint_handler_s(3C)
+ protected:
+ abort_handler_s;
+ ignore_handler_s;
+ memset_s;
+ set_constraint_handler_s;
+} ILLUMOS_0.26;
+
SYMBOL_VERSION ILLUMOS_0.26 { # fts(3) LFS
$if lf64
protected:
diff --git a/usr/src/lib/libc/port/threads/assfail.c b/usr/src/lib/libc/port/threads/assfail.c
index b40e6dc029..1c032d8ea7 100644
--- a/usr/src/lib/libc/port/threads/assfail.c
+++ b/usr/src/lib/libc/port/threads/assfail.c
@@ -95,7 +95,7 @@ Abort(const char *msg)
* Write a panic message w/o grabbing any locks other than assert_lock.
* We have no idea what locks are held at this point.
*/
-static void
+void
common_panic(const char *head, const char *why)
{
char msg[400]; /* no panic() message in the library is this long */
diff --git a/usr/src/lib/libc/sparc/Makefile.com b/usr/src/lib/libc/sparc/Makefile.com
index 7e3397262e..92efd03df5 100644
--- a/usr/src/lib/libc/sparc/Makefile.com
+++ b/usr/src/lib/libc/sparc/Makefile.com
@@ -530,6 +530,7 @@ PORTGEN= \
malloc.o \
memalign.o \
memmem.o \
+ memset_s.o \
mkdev.o \
mkdtemp.o \
mkfifo.o \
@@ -587,6 +588,7 @@ PORTGEN= \
scandir.o \
seekdir.o \
select.o \
+ set_constraint_handler_s.o \
setlabel.o \
setpriority.o \
settimeofday.o \
diff --git a/usr/src/lib/libc/sparcv9/Makefile.com b/usr/src/lib/libc/sparcv9/Makefile.com
index b68eb5c903..b756ad5ab2 100644
--- a/usr/src/lib/libc/sparcv9/Makefile.com
+++ b/usr/src/lib/libc/sparcv9/Makefile.com
@@ -487,6 +487,7 @@ PORTGEN= \
malloc.o \
memalign.o \
memmem.o \
+ memset_s.o \
mkdev.o \
mkdtemp.o \
mkfifo.o \
@@ -544,6 +545,7 @@ PORTGEN= \
scandir.o \
seekdir.o \
select.o \
+ set_constraint_handler_s.o \
setlabel.o \
setpriority.o \
settimeofday.o \
diff --git a/usr/src/man/man3c/Makefile b/usr/src/man/man3c/Makefile
index 2864756ce9..79f54e15dc 100644
--- a/usr/src/man/man3c/Makefile
+++ b/usr/src/man/man3c/Makefile
@@ -241,6 +241,7 @@ MANFILES= __fbufsize.3c \
mbtowc.3c \
membar_ops.3c \
memory.3c \
+ memset_s.3c \
mkfifo.3c \
mkstemp.3c \
mktemp.3c \
@@ -410,6 +411,7 @@ MANFILES= __fbufsize.3c \
sem_unlink.3c \
sem_wait.3c \
semaphore.3c \
+ set_constraint_handler_s.3c \
setbuf.3c \
setbuffer.3c \
setcat.3c \
@@ -559,7 +561,7 @@ MANFILES= __fbufsize.3c \
wordexp.3c \
wsprintf.3c \
wsscanf.3c \
- wstring.3c \
+ wstring.3c
MANLINKS= FD_CLR.3c \
FD_ISSET.3c \
@@ -579,6 +581,7 @@ MANLINKS= FD_CLR.3c \
_exithandle.3c \
_flushlbf.3c \
_setjmp.3c \
+ abort_handler_s.3c \
addrtosymstr.3c \
aiowrite.3c \
alloca.3c \
@@ -889,6 +892,7 @@ MANLINKS= FD_CLR.3c \
htonl.3c \
htonll.3c \
htons.3c \
+ ignore_handler_s.3c \
inet6.3c \
inet_addr.3c \
inet_aton.3c \
@@ -2281,6 +2285,9 @@ sema_post.3c := LINKSRC = semaphore.3c
sema_trywait.3c := LINKSRC = semaphore.3c
sema_wait.3c := LINKSRC = semaphore.3c
+abort_handler_s.3c := LINKSRC = set_constraint_handler_s.3c
+ignore_handler_s.3c := LINKSRC = set_constraint_handler_s.3c
+
setvbuf.3c := LINKSRC = setbuf.3c
setlinebuf.3c := LINKSRC = setbuffer.3c
diff --git a/usr/src/man/man3c/memset_s.3c b/usr/src/man/man3c/memset_s.3c
new file mode 100644
index 0000000000..9da92ff927
--- /dev/null
+++ b/usr/src/man/man3c/memset_s.3c
@@ -0,0 +1,104 @@
+.\"
+.\" This file and its contents are supplied under the terms of the
+.\" Common Development and Distribution License ("CDDL"), version 1.0.
+.\" You may only use this file in accordance with the terms of version
+.\" 1.0 of the CDDL.
+.\"
+.\" A full copy of the text of the CDDL should have accompanied this
+.\" source. A copy of the CDDL is also available via the Internet at
+.\" http://www.illumos.org/license/CDDL.
+.\"
+.\"
+.\" Copyright 2018 Nexenta Systems, Inc.
+.\"
+.Dd August 12, 2017
+.Dt MEMSET_S 3C
+.Os
+.Sh NAME
+.Nm memset_s
+.Nd copy a value to all bytes of a memory buffer
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.Fd #define __STDC_WANT_LIB_EXT1__ 1
+.In string.h
+.Ft errno_t
+.Fo memset_s
+.Fa "void *s"
+.Fa "rsize_t smax"
+.Fa "int c"
+.Fa "rsize_t n"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn memset_s
+function copies the value of
+.Fa c
+.Po converted to an
+.Vt unsigned char
+.Pc
+into each of the first
+.Fa n
+bytes of the memory buffer pointed to by
+.Fa s .
+.Pp
+Unlike the
+.Xr memset 3C ,
+.Fn memset_s
+is guaranteed to never be optimized away by the compiler.
+.Pp
+The
+.Fn memset_s
+function detects the following runtime-constraint violations:
+.Bl -enum
+.It
+.Fa s
+is a
+.Dv NULL
+pointer.
+.It
+.Fa smax
+or
+.Fa n
+is greater than
+.Dv RSIZE_MAX .
+.It
+.Fa n
+is greater than
+.Fa smax
+.Pq buffer overflow .
+.El
+.Pp
+If runtime-constraint violation is detected, and if
+.Fa s
+and
+.Fa smax
+are valid, the
+.Fn memset_s
+function copies the value of
+.Fa c
+.Po converted to an
+.Vt unsigned char
+.Pc
+into each of the first
+.Fa smax
+bytes of the memory buffer pointed to by
+.Fa s
+before calling the runtime-constraint handler.
+.Sh RETURN VALUES
+The
+.Fn memset_s
+function returns 0 if there was no runtime-constraint violation.
+Otherwise, a non-zero value is returned.
+.Sh INTERFACE STABILITY
+.Sy Standard
+.Sh MT-LEVEL
+.Sy Safe
+.Sh SEE ALSO
+.Xr memset 3C ,
+.Xr set_constraint_handler 3C
+.Sh STANDARDS
+The
+.Fn memset_s
+function conforms to
+.St -isoC-2011 .
diff --git a/usr/src/man/man3c/set_constraint_handler_s.3c b/usr/src/man/man3c/set_constraint_handler_s.3c
new file mode 100644
index 0000000000..0b2bd5a165
--- /dev/null
+++ b/usr/src/man/man3c/set_constraint_handler_s.3c
@@ -0,0 +1,133 @@
+.\"
+.\" This file and its contents are supplied under the terms of the
+.\" Common Development and Distribution License ("CDDL"), version 1.0.
+.\" You may only use this file in accordance with the terms of version
+.\" 1.0 of the CDDL.
+.\"
+.\" A full copy of the text of the CDDL should have accompanied this
+.\" source. A copy of the CDDL is also available via the Internet at
+.\" http://www.illumos.org/license/CDDL.
+.\"
+.\"
+.\" Copyright 2018 Nexenta Systems, Inc.
+.\"
+.Dd August 12, 2017
+.Dt SET_CONSTRAINT_HANDLER_S 3C
+.Os
+.Sh NAME
+.Nm set_constraint_handler_s ,
+.Nm abort_handler_s ,
+.Nm ignore_handler_s
+.Nd runtime-constraint handling
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.Fd #define __STDC_WANT_LIB_EXT1__ 1
+.In stdlib.h
+.Ft constraint_handler_t
+.Fo set_constraint_handler_s
+.Fa "constraint_handler_t handler"
+.Fc
+.Ft void
+.Fo abort_handler_s
+.Fa "const char *restrict msg"
+.Fa "void *restrict ptr"
+.Fa "errno_t error"
+.Fc
+.Ft void
+.Fo ignore_handler_s
+.Fa "const char *restrict msg"
+.Fa "void *restrict ptr"
+.Fa "errno_t error"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn set_constraint_handler_s
+function sets the runtime-constraint handler to be
+.Fa handler .
+.Pp
+The runtime-constraint handler is the callback function invoked when a library
+function detects a runtime-constraint violation, having the following prototype:
+.Bd -literal -offset indent
+void (*constraint_handler_t)(const char *restrict msg,
+ void *restrict ptr, errno_t error);
+.Ed
+.Pp
+The arguments are as follows:
+.Bl -tag -width "error"
+.It Fa msg
+A pointer to a character string describing the runtime-constraint violation.
+.It Fa ptr
+A
+.Dv NULL
+pointer.
+.It Fa error
+If the function calling the handler has a return type declared as
+.Vt errno_t ,
+the return value of the function is passed.
+Otherwise, a positive value of type
+.Vt errno_t
+is passed.
+.El
+.Pp
+Only the most recent handler registered with
+.Fn set_constraint_handler_s
+is called when a runtime-constraint violation occurs.
+.Pp
+The implementation has a default constraint handler that is used if no calls to
+the
+.Fn set_constraint_handler_s
+function have been made.
+If the
+.Fa handler
+argument to
+.Fn set_constraint_handler_s
+is a
+.Dv NULL
+pointer, the default handler becomes the current constraint handler.
+.Pp
+The
+.Fn abort_handler_s
+and
+.Fn ignore_handler_s
+are the standard-defined runtime-constraint handlers provided by the C library.
+.Pp
+The
+.Fn abort_handler_s
+function writes the error message including the
+.Fa msg
+to
+.Dv stderr
+and calls the
+.Xr abort 3C
+function.
+The
+.Fn abort_handler_s
+is currently the default runtime-constraint handler.
+.Pp
+The
+.Fn ignore_handler_s
+simply returns to its caller.
+.Sh RETURN VALUES
+The
+.Fn set_constraint_handler_s
+function returns a pointer to the previously registered handler, or
+.Dv NULL
+if none was previously registered.
+.Pp
+The
+.Fn abort_handler_s
+function does not return to its caller.
+.Pp
+The
+.Fn ignore_handler_s
+function returns no value.
+.Sh INTERFACE STABILITY
+.Sy Standard
+.Sh MT-LEVEL
+.Sy Safe
+.Sh STANDARDS
+The
+.Fn set_constraint_handler_s
+function conforms to
+.St -isoC-2011 .
diff --git a/usr/src/pkg/manifests/system-library.man3c.inc b/usr/src/pkg/manifests/system-library.man3c.inc
index 26ae074cb8..c5641365ae 100644
--- a/usr/src/pkg/manifests/system-library.man3c.inc
+++ b/usr/src/pkg/manifests/system-library.man3c.inc
@@ -236,6 +236,7 @@ file path=usr/share/man/man3c/mbstowcs.3c
file path=usr/share/man/man3c/mbtowc.3c
file path=usr/share/man/man3c/membar_ops.3c
file path=usr/share/man/man3c/memory.3c
+file path=usr/share/man/man3c/memset_s.3c
file path=usr/share/man/man3c/mkfifo.3c
file path=usr/share/man/man3c/mkstemp.3c
file path=usr/share/man/man3c/mktemp.3c
@@ -405,6 +406,7 @@ file path=usr/share/man/man3c/sem_timedwait.3c
file path=usr/share/man/man3c/sem_unlink.3c
file path=usr/share/man/man3c/sem_wait.3c
file path=usr/share/man/man3c/semaphore.3c
+file path=usr/share/man/man3c/set_constraint_handler_s.3c
file path=usr/share/man/man3c/setbuf.3c
file path=usr/share/man/man3c/setbuffer.3c
file path=usr/share/man/man3c/setcat.3c
@@ -573,6 +575,8 @@ link path=usr/share/man/man3c/_etext.3c target=end.3c
link path=usr/share/man/man3c/_exithandle.3c target=exit.3c
link path=usr/share/man/man3c/_flushlbf.3c target=__fbufsize.3c
link path=usr/share/man/man3c/_setjmp.3c target=_longjmp.3c
+link path=usr/share/man/man3c/abort_handler_s.3c \
+ target=set_constraint_handler_s.3c
link path=usr/share/man/man3c/addrtosymstr.3c target=walkcontext.3c
link path=usr/share/man/man3c/aiowrite.3c target=aioread.3c
link path=usr/share/man/man3c/alloca.3c target=malloc.3c
@@ -889,6 +893,8 @@ link path=usr/share/man/man3c/htole64.3c target=endian.3c
link path=usr/share/man/man3c/htonl.3c target=byteorder.3c
link path=usr/share/man/man3c/htonll.3c target=byteorder.3c
link path=usr/share/man/man3c/htons.3c target=byteorder.3c
+link path=usr/share/man/man3c/ignore_handler_s.3c \
+ target=set_constraint_handler_s.3c
link path=usr/share/man/man3c/inet6.3c target=inet.3c
link path=usr/share/man/man3c/inet_addr.3c target=inet.3c
link path=usr/share/man/man3c/inet_aton.3c target=inet.3c
diff --git a/usr/src/pkg/manifests/system-test-libctest.mf b/usr/src/pkg/manifests/system-test-libctest.mf
index f2eb069681..135822a5fd 100644
--- a/usr/src/pkg/manifests/system-test-libctest.mf
+++ b/usr/src/pkg/manifests/system-test-libctest.mf
@@ -91,6 +91,8 @@ file path=opt/libc-tests/tests/fnmatch.64 mode=0555
file path=opt/libc-tests/tests/fpround_test mode=0555
file path=opt/libc-tests/tests/fpround_test.$(ARCH) mode=0555
file path=opt/libc-tests/tests/fpround_test.$(ARCH64) mode=0555
+file path=opt/libc-tests/tests/memset_s.32 mode=0555
+file path=opt/libc-tests/tests/memset_s.64 mode=0555
file path=opt/libc-tests/tests/newlocale_test mode=0555
file path=opt/libc-tests/tests/newlocale_test.$(ARCH) mode=0555
file path=opt/libc-tests/tests/newlocale_test.$(ARCH64) mode=0555
@@ -148,6 +150,8 @@ file path=opt/libc-tests/tests/regex/regex_test mode=0555
file path=opt/libc-tests/tests/regex/testregex mode=0555
file path=opt/libc-tests/tests/select/select.sh mode=0555
file path=opt/libc-tests/tests/select/select_test mode=0555
+file path=opt/libc-tests/tests/set_constraint_handler_s.32 mode=0555
+file path=opt/libc-tests/tests/set_constraint_handler_s.64 mode=0555
file path=opt/libc-tests/tests/strcoll-strxfrm-6907.32 mode=0555
file path=opt/libc-tests/tests/strcoll-strxfrm-6907.64 mode=0555
file path=opt/libc-tests/tests/strerror mode=0555
diff --git a/usr/src/test/libc-tests/runfiles/default.run b/usr/src/test/libc-tests/runfiles/default.run
index 15e3d60d69..9c7e893cf6 100644
--- a/usr/src/test/libc-tests/runfiles/default.run
+++ b/usr/src/test/libc-tests/runfiles/default.run
@@ -71,18 +71,22 @@ timeout = 600
[/opt/libc-tests/tests/call_once.32]
[/opt/libc-tests/tests/call_once.64]
[/opt/libc-tests/tests/catopen]
-[/opt/libc-tests/tests/env-7076.32]
-[/opt/libc-tests/tests/env-7076.64]
[/opt/libc-tests/tests/endian.32]
[/opt/libc-tests/tests/endian.64]
+[/opt/libc-tests/tests/env-7076.32]
+[/opt/libc-tests/tests/env-7076.64]
[/opt/libc-tests/tests/fnmatch.32]
[/opt/libc-tests/tests/fnmatch.64]
-[/opt/libc-tests/tests/quick_exit]
-[/opt/libc-tests/tests/psignal]
+[/opt/libc-tests/tests/memset_s.32]
+[/opt/libc-tests/tests/memset_s.64]
[/opt/libc-tests/tests/printf-6961.64]
[/opt/libc-tests/tests/printf-9511.32]
[/opt/libc-tests/tests/printf-9511.64]
[/opt/libc-tests/tests/priv_gettext]
+[/opt/libc-tests/tests/psignal]
+[/opt/libc-tests/tests/quick_exit]
+[/opt/libc-tests/tests/set_constraint_handler_s.32]
+[/opt/libc-tests/tests/set_constraint_handler_s.64]
[/opt/libc-tests/tests/strerror]
[/opt/libc-tests/tests/timespec_get.32]
[/opt/libc-tests/tests/timespec_get.64]
diff --git a/usr/src/test/libc-tests/tests/Makefile b/usr/src/test/libc-tests/tests/Makefile
index 68bd817ed4..88d463294d 100644
--- a/usr/src/test/libc-tests/tests/Makefile
+++ b/usr/src/test/libc-tests/tests/Makefile
@@ -38,10 +38,12 @@ PROGS = \
endian \
env-7076 \
fnmatch \
+ memset_s \
printf-9511 \
psignal-5097 \
quick_exit_order \
quick_exit_status \
+ set_constraint_handler_s \
strcoll-strxfrm-6907 \
timespec_get \
wcsncasecmp \
@@ -62,6 +64,11 @@ PROGS64 = \
aligned_alloc.32 := LDLIBS += -lproc
aligned_alloc.64 := LDLIBS64 += -lproc
+memset_s.32 := CPPFLAGS += -D__STDC_WANT_LIB_EXT1__=1
+memset_s.64 := CPPFLAGS += -D__STDC_WANT_LIB_EXT1__=1
+set_constraint_handler_s.32 := CPPFLAGS += -D__STDC_WANT_LIB_EXT1__=1
+set_constraint_handler_s.64 := CPPFLAGS += -D__STDC_WANT_LIB_EXT1__=1
+
ROOTOPTDIR = $(ROOT)/opt/libc-tests/tests
ROOTOPTPROGS = $(PROGS32:%=$(ROOTOPTDIR)/%) \
$(PROGS64:%=$(ROOTOPTDIR)/%) \
diff --git a/usr/src/test/libc-tests/tests/memset_s.c b/usr/src/test/libc-tests/tests/memset_s.c
new file mode 100644
index 0000000000..4a73459bc5
--- /dev/null
+++ b/usr/src/test/libc-tests/tests/memset_s.c
@@ -0,0 +1,126 @@
+/*
+ * 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 <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+static errno_t e;
+static const char *_RESTRICT_KYWD m;
+
+void
+h(const char *_RESTRICT_KYWD msg, void *_RESTRICT_KYWD ptr, errno_t error)
+{
+ e = error;
+ m = msg;
+}
+
+int
+main(void)
+{
+ char a;
+ char b[3];
+
+ /* null ptr */
+ set_constraint_handler_s(ignore_handler_s);
+ assert(memset_s(0, 1, 1, 1) != 0);
+
+ /* smax > rmax */
+ set_constraint_handler_s(ignore_handler_s);
+ assert(memset_s(&b, RSIZE_MAX + 1, 1, 1) != 0);
+
+ /* smax < 0 */
+ set_constraint_handler_s(ignore_handler_s);
+ assert(memset_s(&a, -1, 1, 1) != 0);
+
+ /* normal */
+ set_constraint_handler_s(ignore_handler_s);
+ a = 3;
+ assert(memset_s(&a, 1, 5, 1) == 0);
+ assert(a == 5);
+
+ /* n > rmax */
+ set_constraint_handler_s(ignore_handler_s);
+ assert(memset_s(&a, 1, 1, RSIZE_MAX + 1) != 0);
+
+ /* n < 0 */
+ set_constraint_handler_s(ignore_handler_s);
+ assert(memset_s(&a, 1, 1, -1) != 0);
+
+ /* n < smax */
+ set_constraint_handler_s(ignore_handler_s);
+ b[0] = 1; b[1] = 2; b[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, handler */
+ set_constraint_handler_s(h);
+ e = 0;
+ m = NULL;
+ b[0] = 1; b[1] = 2; b[2] = 3;
+ 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 */
+ set_constraint_handler_s(h);
+ e = 0;
+ m = NULL;
+ assert(memset_s(&a, RSIZE_MAX + 1, 1, 1) != 0);
+ assert(e > 0);
+ assert(strcmp(m, "memset_s: smax > RSIZE_MAX") == 0);
+
+ /* smax < 0, handler */
+ set_constraint_handler_s(h);
+ e = 0;
+ m = NULL;
+ assert(memset_s(&a, -1, 1, 1) != 0);
+ assert(e > 0);
+ assert(strcmp(m, "memset_s: smax > RSIZE_MAX") == 0);
+
+ /* n > rmax, handler */
+ set_constraint_handler_s(h);
+ e = 0;
+ m = NULL;
+ assert(memset_s(&a, 1, 1, RSIZE_MAX + 1) != 0);
+ assert(e > 0);
+ assert(strcmp(m, "memset_s: n > RSIZE_MAX") == 0);
+
+ /* n < 0, handler */
+ set_constraint_handler_s(h);
+ e = 0;
+ m = NULL;
+ assert(memset_s(&a, 1, 1, -1) != 0);
+ assert(e > 0);
+ assert(strcmp(m, "memset_s: n > RSIZE_MAX") == 0);
+
+ return (0);
+}
diff --git a/usr/src/test/libc-tests/tests/set_constraint_handler_s.c b/usr/src/test/libc-tests/tests/set_constraint_handler_s.c
new file mode 100644
index 0000000000..770d5d46a4
--- /dev/null
+++ b/usr/src/test/libc-tests/tests/set_constraint_handler_s.c
@@ -0,0 +1,44 @@
+/*
+ * 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 <assert.h>
+#include <stdlib.h>
+
+int
+main(void)
+{
+ /* null */
+ assert(set_constraint_handler_s(abort_handler_s) == NULL);
+
+ /* abort handler */
+ set_constraint_handler_s(abort_handler_s);
+ assert(set_constraint_handler_s(ignore_handler_s) == abort_handler_s);
+
+ /* ignore handler */
+ set_constraint_handler_s(ignore_handler_s);
+ assert(set_constraint_handler_s(abort_handler_s) == ignore_handler_s);
+
+ return (0);
+}
diff --git a/usr/src/uts/common/sys/feature_tests.h b/usr/src/uts/common/sys/feature_tests.h
index 18b7de3f70..7e4b4fc67f 100644
--- a/usr/src/uts/common/sys/feature_tests.h
+++ b/usr/src/uts/common/sys/feature_tests.h
@@ -84,7 +84,7 @@ extern "C" {
*
* _STDC_C11 Like _STDC_C99 except that the value of __STDC_VERSION__
* is 201112L indicating a compiler that compiles with
- * ISO/IEXC 9899:2011, otherwise known as the C11 standard.
+ * ISO/IEC 9899:2011, otherwise known as the C11 standard.
*
* _STRICT_SYMBOLS Used in cases where symbol visibility is restricted
* by the standards, and the user has not explicitly
@@ -130,7 +130,7 @@ extern "C" {
* cc -Xs (K&R C) undefined undefined
*
* gcc (default) 1 undefined
- * gcc -ansi, -std={c89, c99,...) 1 defined
+ * gcc -ansi, -std={c89, c99,...) 1 defined
* gcc -traditional (K&R) undefined undefined
*
* The default compilation modes for Sun C compilers versus GNU C compilers
@@ -191,7 +191,7 @@ extern "C" {
* of _POSIX_SOURCE nor _XOPEN_SOURCE is defined and the value of
* __STDC__ does not imply standards conformance).
* - Extended system interfaces are explicitly requested (__EXTENSIONS__
- * is defined).
+ * is defined).
* - Access to in-kernel interfaces is requested (_KERNEL or _KMEMUSER is
* defined). (Note that this dependency is an artifact of the current
* kernel implementation and may change in future releases.)
@@ -436,6 +436,21 @@ extern "C" {
#define _NORETURN_KYWD
#endif
+/* ISO/IEC 9899:2011 Annex K */
+#if !defined(_STRICT_SYMBOLS)
+#define __EXT1_VISIBLE 1
+#else
+#define __EXT1_VISIBLE 0
+#endif
+
+#if defined(__STDC_WANT_LIB_EXT1__)
+#undef __EXT1_VISIBLE
+#if __STDC_WANT_LIB_EXT1__
+#define __EXT1_VISIBLE 1
+#else
+#define __EXT1_VISIBLE 0
+#endif
+#endif /* __STDC_WANT_LIB_EXT1__ */
/*
* The following macro indicates header support for the ANSI C++
@@ -450,12 +465,18 @@ extern "C" {
#define _ISO_C_9899_1999
/*
- * The following macro indicates header support for the C99 standard,
+ * The following macro indicates header support for the C11 standard,
* ISO/IEC 9899:2011, Programming Languages - C.
*/
#define _ISO_C_9899_2011
/*
+ * The following macro indicates header support for the C11 standard,
+ * ISO/IEC 9899:2011 Annex K, Programming Languages - C.
+ */
+#undef __STDC_LIB_EXT1__
+
+/*
* The following macro indicates header support for DTrace. The value is an
* integer that corresponds to the major version number for DTrace.
*/