diff --git a/include/string.h b/include/string.h
index 034e295..3743e53 100644
--- a/include/string.h
+++ b/include/string.h
@@ -44,6 +44,8 @@ extern void *__memchr (const void *__s, int __c, size_t __n)
extern int __ffs (int __i) __attribute__ ((const));
extern char *__strerror_r (int __errnum, char *__buf, size_t __buflen);
+
+extern int __memset_s (void *__s, size_t __szmax, int __c, size_t __n);
#endif
/* Now the real definitions. We do this here since some of the functions
diff --git a/manual/string.texi b/manual/string.texi
index ba5a2c7..af2fba4 100644
--- a/manual/string.texi
+++ b/manual/string.texi
@@ -534,6 +534,18 @@ This function copies the value of @var{c} (converted to an
object beginning at @var{block}. It returns the value of @var{block}.
@end deftypefun
+@comment string.h
+@comment ISO
+@deftypefun int memset_s (void *@var{block}, size_t @var{szmax}, int @var{c}, size_t @var{size})
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+This function copies the value of @var{c} (converted to an
+@code{unsigned char}) into each of the first @var{size} bytes of the
+object beginning at @var{block}. If @var{size} is greater than @var{szmax},
+then only the first @var{szmax} bytes are set, and the function returns
+EOVERFLOW. If @var{block} is NULL, the function returns EINVAL. Otherwise,
+it returns zero.
+@end deftypefun
+
@comment wchar.h
@comment ISO
@deftypefun {wchar_t *} wmemset (wchar_t *@var{block}, wchar_t @var{wc}, size_t @var{size})
diff --git a/string/Makefile b/string/Makefile
index 98c2961..305fabe 100644
--- a/string/Makefile
+++ b/string/Makefile
@@ -32,6 +32,7 @@ routines := strcat strchr strcmp strcoll strcpy strcspn \
strncat strncmp strncpy \
strrchr strpbrk strsignal strspn strstr strtok \
strtok_r strxfrm memchr memcmp memmove memset \
+ memset_s \
mempcpy bcopy bzero ffs ffsll stpcpy stpncpy \
strcasecmp strncase strcasecmp_l strncase_l \
memccpy memcpy wordcopy strsep strcasestr \
@@ -47,7 +48,8 @@ strop-tests := memchr memcmp memcpy memmove mempcpy memset memccpy \
stpcpy stpncpy strcat strchr strcmp strcpy strcspn \
strlen strncmp strncpy strpbrk strrchr strspn memmem \
strstr strcasestr strnlen strcasecmp strncasecmp \
- strncat rawmemchr strchrnul bcopy bzero memrchr
+ strncat rawmemchr strchrnul bcopy bzero memrchr \
+ memset_s
tests := tester inl-tester noinl-tester testcopy test-ffs \
tst-strlen stratcliff tst-svc tst-inlcall \
bug-strncat1 bug-strspn1 bug-strpbrk1 tst-bswap \
diff --git a/string/Versions b/string/Versions
index 59bf35a..a88503f 100644
--- a/string/Versions
+++ b/string/Versions
@@ -80,4 +80,7 @@ libc {
GLIBC_2.6 {
strerror_l;
}
+ GLIBC_2.21 {
+ memset_s;
+ }
}
diff --git a/string/memset_s.c b/string/memset_s.c
new file mode 100644
index 0000000..e9cf95b
--- /dev/null
+++ b/string/memset_s.c
@@ -0,0 +1,55 @@
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ . */
+
+#include
+#include
+#include
+
+#undef memset_s
+
+int
+__memset_s (dstpp, buflen, c, len)
+ void *dstpp;
+ size_t buflen;
+ int c;
+ size_t len;
+{
+ int result = 0;
+
+ if (len > buflen)
+ {
+ result = EOVERFLOW;
+ __set_errno(EOVERFLOW);
+ len = buflen;
+ }
+ else if (NULL == dstpp)
+ {
+ __set_errno(EINVAL);
+ return EINVAL;
+ }
+
+ memset(dstpp, c, len);
+
+ /* Add a barrier to prevent the compiler from optimizing the above memset
+ * away. */
+ __asm__ __volatile__ ( "" : : "r"(dstpp) : "memory" );
+
+ return result;
+}
+weak_alias (__memset_s, memset_s)
+
+
diff --git a/string/string.h b/string/string.h
index c79debc..d7cf6a5 100644
--- a/string/string.h
+++ b/string/string.h
@@ -65,6 +65,12 @@ __BEGIN_NAMESPACE_STD
/* Set N bytes of S to C. */
extern void *memset (void *__s, int __c, size_t __n) __THROW __nonnull ((1));
+#ifdef __STDC_WANT_LIBC_EXT1__
+/* Set N bytes of S to C. */
+int memset_s (void *__s, size_t __szmax, int __c, size_t __n)
+ __THROW __nonnull ((1));
+#endif
+
/* Compare N bytes of S1 and S2. */
extern int memcmp (const void *__s1, const void *__s2, size_t __n)
__THROW __attribute_pure__ __nonnull ((1, 2));
diff --git a/string/test-memset.c b/string/test-memset.c
index 2171b0d..23d398d 100644
--- a/string/test-memset.c
+++ b/string/test-memset.c
@@ -20,6 +20,8 @@
#define TEST_MAIN
#ifdef TEST_BZERO
# define TEST_NAME "bzero"
+#elif defined TEST_MEMSET_S
+# define TEST_NAME "memset_s"
#else
# define TEST_NAME "memset"
#endif
@@ -52,9 +54,23 @@ builtin_bzero (char *s, size_t n)
typedef char *(*proto_t) (char *, int, size_t);
char *builtin_memset (char *, int, size_t);
+#ifdef TEST_MEMSET_S
+char *
+memset_s_wrapper (char *s, int c, size_t n)
+{
+ if (memset_s(s, n, c, n) != 0)
+ return NULL;
+ return s;
+}
+#endif
+
IMPL (simple_memset, 0)
IMPL (builtin_memset, 0)
+#ifdef TEST_MEMSET_S
+IMPL (memset_s_wrapper, 1)
+#else
IMPL (memset, 1)
+#endif
char *
builtin_memset (char *s, int c, size_t n)
diff --git a/string/test-memset_s.c b/string/test-memset_s.c
new file mode 100644
index 0000000..98683a3
--- /dev/null
+++ b/string/test-memset_s.c
@@ -0,0 +1,20 @@
+/* Test and measure bzero functions.
+ Copyright (C) 2012-2014 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ . */
+#define __STDC_WANT_LIBC_EXT1__
+#define TEST_MEMSET_S
+#include "test-memset.c"