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"