From 56540aa3d3a5dc5cd3c56ed0613f5cce36f83810 Mon Sep 17 00:00:00 2001 From: Mostafa Salman Date: Mon, 3 Jun 2024 16:28:16 +0300 Subject: [PATCH] Add Support for Annex K functions according to C11 Adding an implementation of the bounds-checking C functions (as specified in Annex K of the C11 standard) to the PicoLibc. These functions lower the risk of introducing security vulnerabilities such as buffer overflows and format string vulnerabilities into your code by providing clear and easy-to-use interfaces. For each C function a secure alternate function ending in a "_s" postfix is provided (e.g., strcpy_s). Use of these functions is recommended by security experts and secure coding standards. Signed-off-by: Mostafa Salman --- newlib/libc/include/errno.h | 10 + newlib/libc/include/stdint.h | 18 ++ newlib/libc/include/stdlib.h | 23 ++ newlib/libc/include/string.h | 29 ++ newlib/libc/include/sys/errno.h | 2 + newlib/libc/stdlib/CMakeLists.txt | 2 + newlib/libc/stdlib/constraint.c | 55 ++++ newlib/libc/stdlib/meson.build | 2 + newlib/libc/stdlib/rsizet.c | 48 ++++ newlib/libc/stdlib/set_constraint_handler_s.c | 60 ++++ newlib/libc/string/CMakeLists.txt | 10 + newlib/libc/string/memcpy_s.c | 118 ++++++++ newlib/libc/string/memmove_s.c | 102 +++++++ newlib/libc/string/memset_s.c | 94 ++++++ newlib/libc/string/meson.build | 11 + newlib/libc/string/strcat_s.c | 158 ++++++++++ newlib/libc/string/strcpy_s.c | 135 +++++++++ newlib/libc/string/strerror_s.c | 272 ++++++++++++++++++ newlib/libc/string/strerrorlen_s.c | 42 +++ newlib/libc/string/string_private.h | 45 +++ newlib/libc/string/strncat_s.c | 215 ++++++++++++++ newlib/libc/string/strncpy_s.c | 187 ++++++++++++ newlib/libc/string/strnlen_s.c | 64 +++++ newlib/libc/tinystdio/CMakeLists.txt | 1 + newlib/libc/tinystdio/meson.build | 1 + newlib/libc/tinystdio/sprintf_s.c | 153 ++++++++++ newlib/libc/tinystdio/stdio.h | 17 ++ test/CMakeLists.txt | 12 + test/meson.build | 18 ++ test/test-memcpy_s.c | 65 +++++ test/test-memmove_s.c | 65 +++++ test/test-memset_s.c | 64 +++++ test/test-rsize_max_s.c | 80 ++++++ test/test-sprintf_s.c | 66 +++++ test/test-strcat_s.c | 65 +++++ test/test-strcpy_s.c | 65 +++++ test/test-strerror_s.c | 66 +++++ test/test-strerrorlen_s.c | 65 +++++ test/test-strncat_s.c | 65 +++++ test/test-strncpy_s.c | 65 +++++ test/test-strnlen_s.c | 56 ++++ 41 files changed, 2691 insertions(+) create mode 100644 newlib/libc/stdlib/constraint.c create mode 100644 newlib/libc/stdlib/rsizet.c create mode 100644 newlib/libc/stdlib/set_constraint_handler_s.c create mode 100644 newlib/libc/string/memcpy_s.c create mode 100644 newlib/libc/string/memmove_s.c create mode 100644 newlib/libc/string/memset_s.c create mode 100644 newlib/libc/string/strcat_s.c create mode 100644 newlib/libc/string/strcpy_s.c create mode 100644 newlib/libc/string/strerror_s.c create mode 100644 newlib/libc/string/strerrorlen_s.c create mode 100644 newlib/libc/string/string_private.h create mode 100644 newlib/libc/string/strncat_s.c create mode 100644 newlib/libc/string/strncpy_s.c create mode 100644 newlib/libc/string/strnlen_s.c create mode 100644 newlib/libc/tinystdio/sprintf_s.c create mode 100644 test/test-memcpy_s.c create mode 100644 test/test-memmove_s.c create mode 100644 test/test-memset_s.c create mode 100644 test/test-rsize_max_s.c create mode 100644 test/test-sprintf_s.c create mode 100644 test/test-strcat_s.c create mode 100644 test/test-strcpy_s.c create mode 100644 test/test-strerror_s.c create mode 100644 test/test-strerrorlen_s.c create mode 100644 test/test-strncat_s.c create mode 100644 test/test-strncpy_s.c create mode 100644 test/test-strnlen_s.c diff --git a/newlib/libc/include/errno.h b/newlib/libc/include/errno.h index 29c7064ae0..37883d21f2 100644 --- a/newlib/libc/include/errno.h +++ b/newlib/libc/include/errno.h @@ -36,6 +36,16 @@ SUCH DAMAGE. #ifndef __error_t_defined typedef int error_t; + +#ifdef __STDC_WANT_LIB_EXT1__ +#if (__STDC_WANT_LIB_EXT1__ != 0) && (__STDC_WANT_LIB_EXT1__ != 1) +#error Please define __STDC_WANT_LIB_EXT__ as 0 or 1 +#endif +#if __STDC_WANT_LIB_EXT1__ == 1 +typedef int errno_t; +#endif +#endif + #define __error_t_defined 1 #endif diff --git a/newlib/libc/include/stdint.h b/newlib/libc/include/stdint.h index 4abdacb9f2..8bff6d0343 100644 --- a/newlib/libc/include/stdint.h +++ b/newlib/libc/include/stdint.h @@ -458,6 +458,24 @@ typedef __uint_least64_t uint_least64_t; #endif #endif +#ifdef __STDC_WANT_LIB_EXT1__ +#if (__STDC_WANT_LIB_EXT1__ != 0) && (__STDC_WANT_LIB_EXT1__ != 1) +#error Please define __STDC_WANT_LIB_EXT__ as 0 or 1 +#endif + +#if __STDC_WANT_LIB_EXT1__ == 1 + #include + #ifndef __RSIZE_T + #define __RSIZE_T + typedef size_t rsize_t; + #endif + + extern rsize_t _set_rsize_max_s(rsize_t); + extern rsize_t _get_rsize_max_s(void); + #define RSIZE_MAX (_get_rsize_max_s()) +#endif +#endif + #ifdef __cplusplus } diff --git a/newlib/libc/include/stdlib.h b/newlib/libc/include/stdlib.h index 1f77d3a2d1..fd505eac2c 100644 --- a/newlib/libc/include/stdlib.h +++ b/newlib/libc/include/stdlib.h @@ -383,6 +383,29 @@ _Noreturn void quick_exit(int); #endif /* __ISO_C_VISIBLE >= 2011 */ + +#ifdef __STDC_WANT_LIB_EXT1__ +#if (__STDC_WANT_LIB_EXT1__ != 0) && (__STDC_WANT_LIB_EXT1__ != 1) +#error Please define __STDC_WANT_LIB_EXT__ as 0 or 1 +#endif + +#if __STDC_WANT_LIB_EXT1__ == 1 +#include + +typedef void (*constraint_handler_t)( + const char *restrict msg, void *restrict ptr, errno_t error); + +extern constraint_handler_t * ___pcur_handler(void); +#define cur_handler (*___pcur_handler()) + +extern constraint_handler_t set_constraint_handler_s( + constraint_handler_t handler); +extern void ignore_handler_s( + const char *restrict msg, void *restrict ptr, errno_t error); +#endif +#endif + + _END_STD_C #if __SSP_FORTIFY_LEVEL > 0 diff --git a/newlib/libc/include/string.h b/newlib/libc/include/string.h index 7e6e6af282..074fc7c347 100644 --- a/newlib/libc/include/string.h +++ b/newlib/libc/include/string.h @@ -78,6 +78,35 @@ char *strpbrk (const char *, const char *); char *strrchr (const char *, int); size_t strspn (const char *, const char *); char *strstr (const char *, const char *); + + +#ifdef __STDC_WANT_LIB_EXT1__ +#if (__STDC_WANT_LIB_EXT1__ != 0) && (__STDC_WANT_LIB_EXT1__ != 1) +#error Please define __STDC_WANT_LIB_EXT__ as 0 or 1 +#endif + +#if __STDC_WANT_LIB_EXT1__ == 1 +#include +#include + +#ifndef __RSIZE_T +#define __RSIZE_T +typedef size_t rsize_t; +#endif + +extern errno_t memcpy_s(void *__restrict, rsize_t, const void *__restrict, rsize_t); +extern errno_t memset_s(void *, rsize_t, int, rsize_t); +extern errno_t memmove_s(void *, rsize_t, const void *, rsize_t); +extern errno_t strcpy_s(char *__restrict, rsize_t, const char *__restrict); +extern errno_t strcat_s(char *__restrict, rsize_t, const char *__restrict); +extern errno_t strncpy_s(char *__restrict, rsize_t, const char *__restrict, rsize_t); +extern errno_t strncat_s(char *__restrict, rsize_t, const char *__restrict, rsize_t); +extern size_t strnlen_s(const char *, size_t); +extern errno_t strerror_s(char *, rsize_t, errno_t); /* C11 */ +extern size_t strerrorlen_s(errno_t); +#endif +#endif + #ifndef _REENT_ONLY char *strtok (char *__restrict, const char *__restrict); #endif diff --git a/newlib/libc/include/sys/errno.h b/newlib/libc/include/sys/errno.h index 9ff91ce45d..8a9254997c 100644 --- a/newlib/libc/include/sys/errno.h +++ b/newlib/libc/include/sys/errno.h @@ -227,6 +227,8 @@ extern NEWLIB_THREAD_LOCAL_ERRNO int errno; #endif #define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ELAST 149 + #define __ELASTERROR 2000 /* Users can add values starting here */ #ifdef __cplusplus diff --git a/newlib/libc/stdlib/CMakeLists.txt b/newlib/libc/stdlib/CMakeLists.txt index 03c50fa7b7..c887625cd5 100644 --- a/newlib/libc/stdlib/CMakeLists.txt +++ b/newlib/libc/stdlib/CMakeLists.txt @@ -115,6 +115,8 @@ picolibc_sources( pico-exit.c pico-onexit.c pico-cxa-atexit.c + set_constraint_handler_s.c + rsizet.c ) picolibc_sources_flags("-fno-builtin-malloc;-fno-builtin-free" diff --git a/newlib/libc/stdlib/constraint.c b/newlib/libc/stdlib/constraint.c new file mode 100644 index 0000000000..17fb0b3781 --- /dev/null +++ b/newlib/libc/stdlib/constraint.c @@ -0,0 +1,55 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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_WANT_LIB_EXT1__ 1 +#include + +static constraint_handler_t cur_handler = ignore_handler_s; + +constraint_handler_t set_constraint_handler_s(constraint_handler_t handler) { + constraint_handler_t h = cur_handler; + if (handler == (constraint_handler_t)NULL) + cur_handler = ignore_handler_s; // null restores to default handler + else + cur_handler = handler; + return h; + } + +void ignore_handler_s( + const char *restrict msg, void *restrict ptr, errno_t error) { + (void) msg; + (void) ptr; + (void) error; + return; + } diff --git a/newlib/libc/stdlib/meson.build b/newlib/libc/stdlib/meson.build index 6a1eaa3315..511b99c2f7 100644 --- a/newlib/libc/stdlib/meson.build +++ b/newlib/libc/stdlib/meson.build @@ -161,6 +161,8 @@ srcs_stdlib = [ 'wctob.c', 'wctomb.c', 'wctomb_r.c', + 'set_constraint_handler_s.c', + 'rsizet.c', ] srcs_stdlib_stdio = [ diff --git a/newlib/libc/stdlib/rsizet.c b/newlib/libc/stdlib/rsizet.c new file mode 100644 index 0000000000..e4968d72cb --- /dev/null +++ b/newlib/libc/stdlib/rsizet.c @@ -0,0 +1,48 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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_WANT_LIB_EXT1__ 1 +#include + +static rsize_t rsize_max = (SIZE_MAX >> 4); + +rsize_t _set_rsize_max_s(rsize_t maxval) { + rsize_t ret = rsize_max; + rsize_max = maxval; + return ret; + } + +rsize_t _get_rsize_max_s(void) { + return rsize_max; + } diff --git a/newlib/libc/stdlib/set_constraint_handler_s.c b/newlib/libc/stdlib/set_constraint_handler_s.c new file mode 100644 index 0000000000..5d3202227c --- /dev/null +++ b/newlib/libc/stdlib/set_constraint_handler_s.c @@ -0,0 +1,60 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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_WANT_LIB_EXT1__ 1 +#include + +void ignore_handler_s(const char *restrict msg, void *restrict ptr, errno_t error) +{ + (void) msg; + (void) ptr; + (void) error; +} + +constraint_handler_t set_constraint_handler_s(constraint_handler_t handler) +{ + constraint_handler_t h = cur_handler; + + if (handler == (constraint_handler_t)NULL) + { + cur_handler = ignore_handler_s; // null restores to default handler + } + else + { + cur_handler = handler; + } + + return h; +} + diff --git a/newlib/libc/string/CMakeLists.txt b/newlib/libc/string/CMakeLists.txt index 540e16715c..35d9d301e1 100644 --- a/newlib/libc/string/CMakeLists.txt +++ b/newlib/libc/string/CMakeLists.txt @@ -136,4 +136,14 @@ picolibc_sources( wmempcpy.c wmemset.c xpg_strerror_r.c + memcpy_s.c + memmove_s.c + memset_s.c + strcat_s.c + strcpy_s.c + strerror_s.c + strerrorlen_s.c + strncat_s.c + strncpy_s.c + strnlen_s.c ) diff --git a/newlib/libc/string/memcpy_s.c b/newlib/libc/string/memcpy_s.c new file mode 100644 index 0000000000..bbdc45acdf --- /dev/null +++ b/newlib/libc/string/memcpy_s.c @@ -0,0 +1,118 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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_WANT_LIB_EXT1__ 1 +#include +#include +#include +#include + +errno_t memcpy_s(void* restrict s1, rsize_t s1max, const void* restrict s2, rsize_t n) +{ + bool constraint_failure = false; + bool zero_dest = true; + const char* msg = ""; + errno_t rtn = 0; + + if (s1 == NULL) + { + constraint_failure = true; + msg = "memcpy_s: dest is NULL"; + zero_dest = false; + } + + if ((constraint_failure == false) && (s1max > RSIZE_MAX)) + { + constraint_failure = true; + msg = "memcpy_s: buffer size exceeds RSIZE_MAX"; + zero_dest = false; + } + + if ((constraint_failure == false) && (s2 == NULL)) + { + constraint_failure = true; + msg = "memcpy_s: source is NULL"; + } + + if ((constraint_failure == false) && (n > RSIZE_MAX)) + { + constraint_failure = true; + msg = "memcpy_s: copy count exceeds RSIZE_MAX"; + } + + if ((constraint_failure == false) && (n > s1max)) + { + constraint_failure = true; + msg = "memcpy_s: copy count exceeds buffer size"; + } + + if (constraint_failure == false) + { + const char* s1cp = (const char*) s1; + const char* s2cp = (const char*) s2; + const char* s1cp_limit = &s1cp[n]; + const char* s2cp_limit = &s2cp[n]; + + if (((s1cp_limit <= s2cp) || (s2cp_limit <= s1cp)) == false) + { + constraint_failure = true; + msg = "memcpy_s: overlapping copy"; + } + } + + if (constraint_failure == true) + { + constraint_handler_t handler = set_constraint_handler_s(NULL); + (void) set_constraint_handler_s(handler); + + if (zero_dest == true) + { + (void) memset(s1, (int32_t)'\0', s1max); + } + else + { + /* No action required */ + } + + (*handler)(msg, NULL, -1); + rtn = -1; + } + else + { + (void) memcpy(s1, s2, n); + rtn = 0; + } + + return rtn; +} diff --git a/newlib/libc/string/memmove_s.c b/newlib/libc/string/memmove_s.c new file mode 100644 index 0000000000..6b6938299f --- /dev/null +++ b/newlib/libc/string/memmove_s.c @@ -0,0 +1,102 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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_WANT_LIB_EXT1__ 1 +#include +#include +#include +#include + +errno_t memmove_s(void* s1, rsize_t s1max, const void* s2, rsize_t n) +{ + bool constraint_failure = false; + bool zero_dest = true; + const char* msg = ""; + errno_t rtn = 0; + + if (s1 == NULL) + { + constraint_failure = true; + msg = "memmove_s: dest is NULL"; + zero_dest = false; + } + + if ((constraint_failure == false) && (s1max > RSIZE_MAX)) + { + constraint_failure = true; + msg = "memmove_s: buffer size exceeds RSIZE_MAX"; + zero_dest = false; + } + + if ((constraint_failure == false) && (s2 == NULL)) + { + constraint_failure = true; + msg = "memmove_s: source is NULL"; + } + + if ((constraint_failure == false) && (n > RSIZE_MAX)) + { + constraint_failure = true; + msg = "memmove_s: copy count exceeds RSIZE_MAX"; + } + + if ((constraint_failure == false) && (n > s1max)) + { + constraint_failure = true; + msg = "memmove_s: copy count exceeds buffer size"; + } + + /* overlapping memory is allowed for memmove_s so no checks for that */ + + if (constraint_failure == true) + { + constraint_handler_t handler = set_constraint_handler_s(NULL); + (void) set_constraint_handler_s(handler); + + if (zero_dest == true) + { + (void) memset(s1, (int32_t)'\0', s1max); + } + + (*handler)(msg, NULL, -1); + rtn = -1; + } + else + { + (void) memmove(s1, s2, n); + rtn = 0; + } + + return rtn; +} diff --git a/newlib/libc/string/memset_s.c b/newlib/libc/string/memset_s.c new file mode 100644 index 0000000000..7ae6947557 --- /dev/null +++ b/newlib/libc/string/memset_s.c @@ -0,0 +1,94 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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_WANT_LIB_EXT1__ 1 +#include +#include +#include +#include + +errno_t memset_s(void* s, rsize_t smax, int c, rsize_t n) +{ + bool constraint_failure = false; + bool fill_dest = true; + const char* msg = ""; + errno_t rtn = 0; + + if (s == NULL) + { + constraint_failure = true; + msg = "memset_s: dest is NULL"; + fill_dest = false; + } + + if ((constraint_failure == false) && (smax > RSIZE_MAX)) + { + constraint_failure = true; + msg = "memset_s: buffer size exceeds RSIZE_MAX"; + fill_dest = false; + } + + if ((constraint_failure == false) && (n > RSIZE_MAX)) + { + constraint_failure = true; + msg = "memset_s: count exceeds RSIZE_MAX"; + } + + if ((constraint_failure == false) && (n > smax)) + { + constraint_failure = true; + msg = "memset_s: count exceeds buffer size"; + } + + if (constraint_failure == true) + { + constraint_handler_t handler = set_constraint_handler_s(NULL); + (void) set_constraint_handler_s(handler); + + if (fill_dest == true) + { + (void) memset(s, c, smax); + } + + (*handler)(msg, NULL, -1); + rtn = -1; + } + else + { + (void) memset(s, c, n); + rtn = 0; + } + + return rtn; +} diff --git a/newlib/libc/string/meson.build b/newlib/libc/string/meson.build index 8ae845d9be..eb44568e1d 100644 --- a/newlib/libc/string/meson.build +++ b/newlib/libc/string/meson.build @@ -135,11 +135,22 @@ srcs_string = [ 'wmempcpy.c', 'wmemset.c', 'xpg_strerror_r.c', + 'memcpy_s.c', + 'memmove_s.c', + 'memset_s.c', + 'strcat_s.c', + 'strcpy_s.c', + 'strerror_s.c', + 'strerrorlen_s.c', + 'strncat_s.c', + 'strncpy_s.c', + 'strnlen_s.c', ] hdrs_string = [ 'local.h', 'str-two-way.h', + 'string_private.h', ] srcs_strcmp = [ diff --git a/newlib/libc/string/strcat_s.c b/newlib/libc/string/strcat_s.c new file mode 100644 index 0000000000..caa41dbd83 --- /dev/null +++ b/newlib/libc/string/strcat_s.c @@ -0,0 +1,158 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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_WANT_LIB_EXT1__ 1 +#include +#include +#include +#include + +errno_t strcat_s(char *restrict s1, rsize_t s1max, const char *restrict s2) { + bool constraint_failure = false; + const char *msg = ""; + size_t s1_len = 0; + + bool write_null = true; + if (!constraint_failure) { + if (s1 == NULL) { + constraint_failure = true; + msg = "strcat_s: dest is NULL"; + write_null = false; + } + } + + if (!constraint_failure) { + if (s1max == 0 || s1max > RSIZE_MAX) { + constraint_failure = true; + msg = "strcat_s: dest buffer size is 0 or exceeds RSIZE_MAX"; + write_null = false; + } + } + + if (!constraint_failure) { + if (s2 == NULL) { + constraint_failure = true; + msg = "strcat_s: source is NULL"; + } + } + + /* It is a constraint violation if s1max is not large enough to contain + * the concatenation s2: no truncation permitted. + * It is also a constraint violation if the string pointed to by s2 + * overlaps s1 in any way. + * The C11 Rationale says we are permitted to proceed with the copy and + * detect dest buffer overrun and overlapping memory blocks as a byproduct + * of performing the copy operation. This is to avoid calling strlen on + * s2 to detect these violations prior to attempting the copy. + */ + if (!constraint_failure) { + // compute chars available in s1 + s1_len = strnlen_s(s1, s1max); + if (s1_len == s1max) { + constraint_failure = true; + msg = "strcat_s: string 1 length exceeds buffer size"; + } + } + + if (!constraint_failure) { + const char *overlap_point; + bool check_s1_for_overlap; + unsigned m = s1max - s1_len; + char *s1cp = s1 + s1_len; + const char *s2cp = s2; + // Question; at this point should we just return + // strcpy_s(s1cp, m, s2) ? + if (s1 <= s2) { + // if we ever reach s2 when storing to s1 we have overlap + overlap_point = s2; + check_s1_for_overlap = true; + // make sure source does not lie within initial dest string. + if (s2 <= s1cp) { + constraint_failure = true; + msg = "strcat_s: overlapping copy"; + } + } + else { + // if we ever reach s1 when reading from s2 we have overlap + overlap_point = s1; + check_s1_for_overlap = false; + // issue with checking initial dest string does not apply in this + // case, overlap will be detected only by hitting overlap_point. + } + if (!constraint_failure) { + unsigned written = 0; + char c = '.'; + while (written < m) { + if (check_s1_for_overlap) { + if (s1cp == overlap_point) { + constraint_failure = true; + } + } + else if (s2cp == overlap_point) { + constraint_failure = true; + } + if (constraint_failure) { + break; + } + c = *s2cp++; + *s1cp++ = c; + written++; + if (c == '\0') { + break; + } + + } + if (constraint_failure) { + msg = "strcat_s: overlapping copy"; + } + else if (c != '\0') { + constraint_failure = true; + msg = "strcat_s: dest buffer size insufficent to append string"; + } + } + + } + + + if (constraint_failure) { + constraint_handler_t handler = set_constraint_handler_s(NULL); + set_constraint_handler_s(handler); + if (write_null) + *s1 = '\0'; + (*handler)(msg, NULL, -1); + return -1; + } + else + return 0; + } diff --git a/newlib/libc/string/strcpy_s.c b/newlib/libc/string/strcpy_s.c new file mode 100644 index 0000000000..6d2822af53 --- /dev/null +++ b/newlib/libc/string/strcpy_s.c @@ -0,0 +1,135 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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_WANT_LIB_EXT1__ 1 +#include +#include +#include +#include + +errno_t strcpy_s(char *restrict s1, rsize_t s1max, const char *restrict s2) { + bool constraint_failure = false; + const char *msg = ""; + + bool write_null = true; + if (!constraint_failure) { + if (s1 == NULL) { + constraint_failure = true; + msg = "strcpy_s: dest is NULL"; + write_null = false; + } + } + + if (!constraint_failure) { + if (s1max == 0 || s1max > RSIZE_MAX) { + constraint_failure = true; + msg = "strcpy_s: dest buffer size is 0 or exceeds RSIZE_MAX"; + write_null = false; + } + } + + if (!constraint_failure) { + if (s2 == NULL) { + constraint_failure = true; + msg = "strcpy_s: source is NULL"; + } + } + + /* It is a constraint violation if s1max is not large enough to contain + * s2: no truncation permitted. + * It is also a constraint violation if the string pointed to by s2 + * overlaps s1 in any way. + * The C11 Rationale says we are permitted to proceed with the copy and + * detect dest buffer overrun and overlapping memory blocks as a byproduct + * of performing the copy operation. This is to avoid calling strlen on + * s2 to detect these violations prior to attempting the copy. + */ + if (!constraint_failure) { + const char *overlap_point; + bool check_s1_for_overlap; + char *s1cp = s1; + const char *s2cp = s2; + if (s1 < s2) { + // if we ever reach s2 when storing to s1 we have overlap + overlap_point = s2; + check_s1_for_overlap = true; + } + else { + // if we ever reach s1 when reading from s2 we have overlap + overlap_point = s1; + check_s1_for_overlap = false; + } + unsigned written = 0; + char c = '.'; + while (written < s1max) { + if (check_s1_for_overlap) { + if (s1cp == overlap_point) { + constraint_failure = true; + } + } + else if (s2cp == overlap_point) { + constraint_failure = true; + } + if (constraint_failure) { + break; + } + c = *s2cp++; + *s1cp++ = c; + written++; + if (c == '\0') { + break; + } + + } + + if (constraint_failure) { + msg = "strcpy_s: overlapping copy"; + } + else if (c != '\0') { + constraint_failure = true; + msg = "strcpy_s: dest buffer size insufficent to copy string"; + } + } + + if (constraint_failure) { + constraint_handler_t handler = set_constraint_handler_s(NULL); + set_constraint_handler_s(handler); + if (write_null) + *s1 = '\0'; + (*handler)(msg, NULL, -1); + return -1; + } + else + return 0; + } diff --git a/newlib/libc/string/strerror_s.c b/newlib/libc/string/strerror_s.c new file mode 100644 index 0000000000..43432f1087 --- /dev/null +++ b/newlib/libc/string/strerror_s.c @@ -0,0 +1,272 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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_WANT_LIB_EXT1__ 1 +#include +#include +#include +#include +#include +#include "string_private.h" + +const char *error_string(errno_t errnum) +{ + static const char * const _sys_errlist[] = + { + "No error", /* 0 */ + "Not owner", + "No such file or directory", + "No such process", + "Interrupted system call", + "I/O error", + "No such device or address", + "Arg list too long", + "Exec format error", + "Bad file number", + "No children", /* 10 */ + "No more processes", + "Not enough core", + "Permission denied", + "Bad address", + "Block device required", + "Mount device busy", + "File exists", + "Cross-device link", + "No such device", + "Not a directory", /* 20 */ + "Is a directory", + "Invalid argument", + "File table overflow", + "Too many open files", + "Not a typewriter", + "Text file busy", + "File too large", + "No space left on device", + "Illegal seek", + "Read-only file system", /* 30 */ + "Too many links", + "Broken pipe", + "Mathematics argument out of domain of function", + "Result too large", + "No message of desired type", + "Identifier removed", + "Channel number out of range", + "Level 2 not synchronized", + "Level 3 halted", + "Level 3 reset", /* 40 */ + "Link number out of range", + "Protocol driver not attached", + "No CSI structure available", + "Level 2 halted", + "Deadlock", + "No lock", + "unknown error", + "unknown error", + "unknown error", + "Invalid exchange", /* 50 */ + "Invalid request descriptor", + "Exchange full", + "No anode", + "Invalid request code", + "Invalid slot", + "File locking deadlock error", + "Bad font file fmt", + "unknown error", + "unknown error", + "Not a stream", /* 60 */ + "No data (for no delay io)", + "Stream ioctl timeout", + "No stream resources", + "Machine is not on the network", + "Package not installed", + "The object is remote", + "Virtual circuit is gone", + "Advertise error", + "Srmount error", + "Communication error on send", /* 70 */ + "Protocol error", + "unknown error", + "unknown error", + "Multihop attempted", + "Inode is remote (not really error)", + "Cross mount point (not really error)", + "Bad message", + "unknown error", + "Inappropriate file type or format", + "Given log. name not unique", /* 80 */ + "File descriptor in bad state", + "Remote address changed", + "Can't access a needed shared lib", + "Accessing a corrupted shared lib", + ".lib section in a.out corrupted", + "Attempting to link in too many libs", + "Attempting to exec a shared library", + "Function not implemented", + "No more files", + "Directory not empty", /* 90 */ + "File or path name too long", + "Too many symbolic links", + "unknown error", + "unknown error", + "Operation not supported on socket", + "Protocol family not supported", + "unknown error", + "unknown error", + "unknown error", + "unknown error", /* 100 */ + "unknown error", + "unknown error", + "unknown error", + "Connection reset by peer", + "No buffer space available", + "Address family not supported by protocol family", + "Protocol wrong type for socket", + "Socket operation on non-socket", + "Protocol not available", + "Can't send after socket shutdown", /* 110 */ + "Connection refused", + "Address already in use", + "Software caused connection abort", + "Network is unreachable", + "Network interface is not configured", + "Connection timed out", + "Host is down", + "Host is unreachable", + "Connection already in progress", + "Socket already connected", /* 120 */ + "Destination address required", + "Message too long", + "Unknown protocol", + "Socket type not supported", + "Address not available", + "Connection aborted by network", + "Socket is already connected", + "Socket is not connected", + "Too many references: cannot splice", + "Too many processes", /* 130 */ + "Too many users", + "Reserved", + "Reserved", + "Not supported", + "No medium found", + "unknown error", + "unknown error", + "Illegal byte sequence", + "Value too large for defined data type", + "Operation canceled", /* 140 */ + "State not recoverable", + "Previous owner died", + "Streams pipe error", + "Memory page has hardware error", + "Is a named type file", + "Key has expired", + "Key was rejected by service", + "Key has been revoked", + NULL + }; + + const char *cp; + if ((uint32_t)errnum < SYS_NERR) + { + cp = SYS_ERRLIST(errnum); + } + else + { + /* Standard says any value of type int shall be mapped to a message */ + cp = "unknown error"; + } + return cp; +} + +/* C11 version; required by LLVM's C++11 library */ +errno_t strerror_s(char *buf, rsize_t buflen, errno_t errnum) +{ + int32_t result = 0; + bool constraint_failure = false; + const char *msg = ""; + + + if (buf == NULL) + { + constraint_failure = true; + msg = "strerror_s: dest is NULL"; + } + + if (constraint_failure == false) + { + if ((buflen == 0u) || (buflen > RSIZE_MAX)) + { + constraint_failure = true; + msg = "strerror_s: dest buffer size is 0 or exceeds RSIZE_MAX"; + } + } + + if (constraint_failure == false) + { + const char *cp = error_string(errnum); + uint32_t len = strnlen_s(cp, MAX_ERROR_MSG); + + if (len < buflen) + { + (void)strncpy(buf, cp, MAX_ERROR_MSG); + } + else + { + /* Standard allows truncation of error message with '...' to + indicate truncation. */ + (void)memcpy(buf, cp, (buflen - 1u)); + buf[(buflen - 1u)] = '\0'; + + if (buflen > 3u) + { + (void)strncpy(&buf[(buflen - 4u)], "...", 4u); + } + + result = ERANGE; + } + + } + + if (constraint_failure == true) + { + constraint_handler_t handler = set_constraint_handler_s(NULL); + + (void)set_constraint_handler_s(handler); + (*handler)(msg, NULL, -1); + + result = -1; + } + + return result; +} diff --git a/newlib/libc/string/strerrorlen_s.c b/newlib/libc/string/strerrorlen_s.c new file mode 100644 index 0000000000..9aca44d9df --- /dev/null +++ b/newlib/libc/string/strerrorlen_s.c @@ -0,0 +1,42 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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_WANT_LIB_EXT1__ 1 +#include +#include "string_private.h" + +size_t strerrorlen_s(errno_t errnum) +{ + return strnlen_s(error_string(errnum), MAX_ERROR_MSG); +} diff --git a/newlib/libc/string/string_private.h b/newlib/libc/string/string_private.h new file mode 100644 index 0000000000..e6c9bd1b36 --- /dev/null +++ b/newlib/libc/string/string_private.h @@ -0,0 +1,45 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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. + */ +#ifndef STRING_PRIVATE_H_ +#define STRING_PRIVATE_H_ + +#define SYS_NERR ELAST +#define SYS_ERRLIST(n) _sys_errlist[(n)] +#define MAX_ERROR_MSG 50 + +const char *error_string(errno_t errnum); + + +#endif //STRING_PRIVATE_H_ diff --git a/newlib/libc/string/strncat_s.c b/newlib/libc/string/strncat_s.c new file mode 100644 index 0000000000..25627a692d --- /dev/null +++ b/newlib/libc/string/strncat_s.c @@ -0,0 +1,215 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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_WANT_LIB_EXT1__ 1 +#include +#include +#include +#include + +errno_t strncat_s(char *restrict s1, rsize_t s1max, const char *restrict s2, + rsize_t n) +{ + bool constraint_failure = false; + const char *msg = ""; + size_t s1_len = 0; + bool write_null = true; + errno_t rtn = 0; + + s1_len = strnlen_s(s1, s1max); + + if (s1 == NULL) + { + constraint_failure = true; + msg = "strncat_s: dest is NULL"; + write_null = false; + } + else if ( (s1max == 0u) || (s1max > RSIZE_MAX)) + { + constraint_failure = true; + msg = "strncat_s: dest buffer size is 0 or exceeds RSIZE_MAX"; + write_null = false; + } + else if (s2 == NULL) + { + constraint_failure = true; + msg = "strncat_s: source is NULL"; + } + else if (n > RSIZE_MAX) + { + constraint_failure = true; + msg = "strncat_s: copy count exceeds RSIZE_MAX"; + } + + /* It is a constraint violation if s1max is not large enough to contain + * the concatenation of s2. + * It is also a constraint violation if the string pointed to by s2 + * overlaps s1 in any way. + * The C11 Rationale says we are permitted to proceed with the copy and + * detect dest buffer overrun and overlapping memory blocks as a byproduct + * of performing the copy operation. This is to avoid calling strlen on + * s2 to detect these violations prior to attempting the copy. + */ + // compute chars available in s1 + + else if (s1_len == s1max) + { + constraint_failure = true; + msg = "strcat_s: string 1 length exceeds buffer size"; + } + else + { + // compute chars available in s1 + uint32_t m = (s1max - s1_len); + uint32_t i = 0; + char *s1cp = s1; + + for (i = 0u; i < s1_len; i++) + { + s1cp++; + } + + // Question; at this point should we just return + // strncpy_s(s1cp, m, s2, n) ? + // perhaps not since overlap check needs to be over entire s1 vs. s2? + + const char *overlap_point; + bool check_s1_for_overlap; + const char *s2cp = s2; + + if (s1 <= s2) + { + // if we ever reach s2 when storing to s1 we have overlap + overlap_point = s2; + check_s1_for_overlap = true; + // make sure source does not lie within initial dest string. + if (s2 <= s1cp) + { + constraint_failure = true; + msg = "strcat_s: overlapping copy"; + } + } + else + { + // if we ever reach s1 when reading from s2 we have overlap + overlap_point = s1; + check_s1_for_overlap = false; + } + + uint32_t written = 0; + char c = '.'; + + while ((written < m) && (written < n)) + { + if (check_s1_for_overlap == true) + { + if (s1cp == overlap_point) + { + constraint_failure = true; + } + } + else if (s2cp == overlap_point) + { + constraint_failure = true; + } + else + { + /* Normal case*/ + } + + if (constraint_failure == false) + { + c = *s2cp; + s2cp++; + *s1cp = c; + s1cp++; + written++; + } + + if ((constraint_failure == true) || (c == '\0')) + { + break; + } + } + + if ( (c != '\0') && (written == n) && (written < m)) + { + // we copied n chars from s2 and there is room for null char in s1 + if ((check_s1_for_overlap== true) && (s1cp == overlap_point)) + { + constraint_failure = true; + } + else + { + c = '\0'; + *s1cp = '\0'; + } + } + + if (constraint_failure == true) + { + msg = "strncat_s: overlapping copy"; + } + else if (c != '\0') + { + constraint_failure = true; + msg = "strncat_s: dest buffer size insufficent to copy string"; + } + else + { + /*No Error*/ + } + } + + if (constraint_failure == true) + { + constraint_handler_t handler = set_constraint_handler_s(NULL); + (void)set_constraint_handler_s(handler); + + if (write_null == true) + { + *s1 = '\0'; + } + + ( *handler)(msg, NULL, -1); + + rtn = -1; + } + else + { + rtn = 0; + } + + return rtn; +} diff --git a/newlib/libc/string/strncpy_s.c b/newlib/libc/string/strncpy_s.c new file mode 100644 index 0000000000..3d608636dd --- /dev/null +++ b/newlib/libc/string/strncpy_s.c @@ -0,0 +1,187 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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_WANT_LIB_EXT1__ 1 +#include +#include +#include +#include + +errno_t strncpy_s(char *restrict s1, rsize_t s1max, const char *restrict s2, + rsize_t n) +{ + bool constraint_failure = false; + const char *msg = ""; + bool write_null = true; + errno_t rtn = 0; + + if (s1 == NULL) + { + constraint_failure = true; + msg = "strncpy_s: dest is NULL"; + write_null = false; + } + else if ((s1max == 0u) || (s1max > RSIZE_MAX)) + { + constraint_failure = true; + msg = "strncpy_s: dest buffer size is 0 or exceeds RSIZE_MAX"; + write_null = false; + } + + else if (s2 == NULL) + { + constraint_failure = true; + msg = "strncpy_s: source is NULL"; + } + else if (n > RSIZE_MAX) + { + constraint_failure = true; + msg = "strncpy_s: copy count exceeds RSIZE_MAX"; + } + + /* It is a constraint violation if s1max is not large enough to contain + * a copy of s2 (with n as upper bound on chars copied). + * It is also a constraint violation if the string pointed to by s2 + * overlaps s1 in any way. + * The C11 Rationale says we are permitted to proceed with the copy and + * detect dest buffer overrun and overlapping memory blocks as a byproduct + * of performing the copy operation. This is to avoid calling strlen on + * s2 to detect these violations prior to attempting the copy. + */ + + else + { + const char *overlap_point; + bool check_s1_for_overlap; + char *s1cp = s1; + const char *s2cp = s2; + + if (s1 < s2) + { + // if we ever reach s2 when storing to s1 we have overlap + overlap_point = s2; + check_s1_for_overlap = true; + } + else + { + // if we ever reach s1 when reading from s2 we have overlap + overlap_point = s1; + check_s1_for_overlap = false; + } + + uint32_t written = 0; + char c = '.'; + + while ((written < s1max) && (written < n)) + { + if (check_s1_for_overlap == true) + { + if (s1cp == overlap_point) + { + constraint_failure = true; + } + } + else if (s2cp == overlap_point) + { + constraint_failure = true; + } + else + { + /* Normal case*/ + } + + if (constraint_failure == false) + { + c = *s2cp; + s2cp++; + *s1cp = c; + s1cp++; + written++; + } + + if ((constraint_failure == true) || (c == '\0')) + { + break; + } + } + + if ((c != '\0') && (written == n) && (written < s1max)) + { + // we copied n chars from s2 and there is room for null char in s1 + if ((check_s1_for_overlap == true) && (s1cp == overlap_point)) + { + constraint_failure = true; + } + else + { + c = '\0'; + *s1cp = '\0'; + } + } + + if (constraint_failure == true) + { + msg = "strncpy_s: overlapping copy"; + } + else if (c != '\0') + { + constraint_failure = true; + msg = "strncpy_s: dest buffer size insufficent to copy string"; + } + else + { + /*No Error*/ + } + } + + if (constraint_failure == true) + { + constraint_handler_t handler = set_constraint_handler_s(NULL); + (void)set_constraint_handler_s(handler); + + if (write_null == true) + { + *s1 = '\0'; + } + + (*handler)(msg, NULL, -1); + rtn = -1; + } + else + { + rtn = 0; + } + + return rtn; +} diff --git a/newlib/libc/string/strnlen_s.c b/newlib/libc/string/strnlen_s.c new file mode 100644 index 0000000000..75a513fa35 --- /dev/null +++ b/newlib/libc/string/strnlen_s.c @@ -0,0 +1,64 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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_WANT_LIB_EXT1__ 1 +#include + +size_t strnlen_s(const char *s, size_t maxsize) +{ + const void *s_end; + size_t rtn = 0; + + if (s == NULL) + { + rtn = 0; + } + else + { + s_end = memchr((const void *)s, (int) '\0', maxsize); + + if (s_end == NULL) + { + rtn = maxsize; + } + else + { + int s_size; + s_size = s_end - (const void *)s; + rtn = (size_t) s_size; + } + } + + return rtn; +} diff --git a/newlib/libc/tinystdio/CMakeLists.txt b/newlib/libc/tinystdio/CMakeLists.txt index e2dce36404..fb32c5c1d6 100644 --- a/newlib/libc/tinystdio/CMakeLists.txt +++ b/newlib/libc/tinystdio/CMakeLists.txt @@ -162,6 +162,7 @@ picolibc_sources( vwscanf.c wprintf.c wscanf.c + sprintf_s.c ) picolibc_sources( diff --git a/newlib/libc/tinystdio/meson.build b/newlib/libc/tinystdio/meson.build index b0161519e8..107b4aa202 100644 --- a/newlib/libc/tinystdio/meson.build +++ b/newlib/libc/tinystdio/meson.build @@ -163,6 +163,7 @@ srcs_tinystdio = [ 'vwscanf.c', 'wprintf.c', 'wscanf.c', + 'sprintf_s.c', ] # exact float/string conversion code diff --git a/newlib/libc/tinystdio/sprintf_s.c b/newlib/libc/tinystdio/sprintf_s.c new file mode 100644 index 0000000000..f76645ad56 --- /dev/null +++ b/newlib/libc/tinystdio/sprintf_s.c @@ -0,0 +1,153 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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_WANT_LIB_EXT1__ 1 +#include "stdio_private.h" +#include +#include +#include +#include +#include +#include + +int sprintf_s(char *restrict s, rsize_t bufsize, + const char * restrict fmt, ...) { + bool constraint_failure = false; + bool write_null = true; + const char *msg = ""; + va_list args; + int rc; + + if (s == NULL) + { + constraint_failure = true; + write_null = false; + msg = "sprintf_s: dest buffer is null"; + } + else if (bufsize == 0 || bufsize > RSIZE_MAX) + { + constraint_failure = true; + write_null = false; + msg = "sprintf_s: invalid buffer size"; + } + else if (fmt == NULL) + { + constraint_failure = true; + msg = "sprintf_s: null format string"; + } + else if (strstr(fmt, " %n") != NULL) + { + constraint_failure = true; + msg = "sprintf_s: format string contains percent-n"; + } + else + { + va_start(args, fmt); + + va_list args_copy; + va_copy(args_copy, args); + + const char *check_ptr = fmt; + uint8_t null_str = 0; + while (*check_ptr && null_str == 0) + { + if (check_ptr[0] == '%') + { + switch(check_ptr[1]) + { + case 's': + { + char *str_arg = va_arg(args_copy, char *); + if (str_arg == NULL) + { + constraint_failure = true; + msg = "sprintf_s: null string argument"; + va_end(args_copy); + va_end(args); + null_str = 1; + } + break; + } + case 'd': case 'i': case 'u': case 'o': case 'x': case 'X': + case 'c': case 'h': case 'l': case 'L': case 'z': case 't': + va_arg(args_copy, int); + break; + case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': case 'a': case 'A': + va_arg(args_copy, double); + break; + case 'p': + va_arg(args_copy, void *); + break; + default: + break; + } + + } + check_ptr++; + } + + if (constraint_failure == false) + { + rc = vsnprintf(s, bufsize, fmt, args); + va_end(args_copy); + va_end(args); + } + + } + + if (constraint_failure == false) + { + if (rc < 0 || rc >= (int)bufsize) + { + constraint_failure = true; + msg = "sprintf_s: dest buffer overflow"; + } + else + { + s[rc] = 0; + } + } + + if (constraint_failure == true) + { + constraint_handler_t handler = set_constraint_handler_s(NULL); + (void) set_constraint_handler_s(handler); + (*handler)(msg, NULL, -1); + rc = 0; /* standard stipulates this */ + if (write_null) + s[0] = '\0'; /* again, standard requires this */ + } + + return(rc); +} \ No newline at end of file diff --git a/newlib/libc/tinystdio/stdio.h b/newlib/libc/tinystdio/stdio.h index c33f51e8c1..a0f1fda6be 100644 --- a/newlib/libc/tinystdio/stdio.h +++ b/newlib/libc/tinystdio/stdio.h @@ -324,6 +324,23 @@ char *tmpnam (char *s); ssize_t getline(char **__restrict lineptr, size_t *__restrict n, FILE *__restrict stream); ssize_t getdelim(char **__restrict lineptr, size_t *__restrict n, int delim, FILE *__restrict stream); +#ifdef __STDC_WANT_LIB_EXT1__ +#if (__STDC_WANT_LIB_EXT1__ != 0) && (__STDC_WANT_LIB_EXT1__ != 1) +#error Please define __STDC_WANT_LIB_EXT__ as 0 or 1 +#endif + +#if __STDC_WANT_LIB_EXT1__ == 1 +#include + +#ifndef __RSIZE_T +#define __RSIZE_T +typedef size_t rsize_t; +#endif +extern int sprintf_s(char *__restrict __s, rsize_t __bufsize, + const char *__restrict __format, ...); +#endif +#endif + /* * The format of tmpnam names is TXXXXXX, which works with mktemp */ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9011ae6fda..d5b835a6fa 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -59,6 +59,18 @@ set(tests test-fma malloc_stress posix-io + test-memcpy_s + test-memset_s + test-memmove_s + test-strcat_s + test-strcpy_s + test-strerror_s + test-strerrorlen_s + test-strncat_s + test-strncpy_s + test-strnlen_s + test-rsize_max_s + test-sprintf_s ) set(tests_fail diff --git a/test/meson.build b/test/meson.build index d9dac7038e..bbd219ec93 100644 --- a/test/meson.build +++ b/test/meson.build @@ -548,6 +548,24 @@ foreach target : targets plain_tests += 'stack-smash' endif + plain_tests += ['test-memcpy_s', + 'test-memset_s', + 'test-memmove_s', + 'test-strcat_s', + 'test-strcpy_s', + 'test-strerror_s', + 'test-strerrorlen_s', + 'test-strncat_s', + 'test-strncpy_s', + 'test-strnlen_s', + 'test-rsize_max_s', + ] + + if tinystdio + plain_tests += 'test-sprintf_s' + endif + + foreach t1 : plain_tests t1_src = t1 + '.c' if target == '' diff --git a/test/test-memcpy_s.c b/test/test-memcpy_s.c new file mode 100644 index 0000000000..104be62668 --- /dev/null +++ b/test/test-memcpy_s.c @@ -0,0 +1,65 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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_WANT_LIB_EXT1__ 1 +#include +#include +#include +#include + +#undef cur_handler +static constraint_handler_t cur_handler; + +constraint_handler_t *___pcur_handler(void) { + return &cur_handler; + } + +int main(void) +{ + char src[] = "ABCDEF"; + char dst[10]; + + errno_t err = memcpy_s( dst, sizeof(dst), src, strlen(src)+1 ); + if (err == 0) + { + printf("memcpy_s sucessful: %s\n", dst); + return 0; + } + else + { + printf("memcpy_s failed: %s\n", strerror(err)); + return -1; + } +} \ No newline at end of file diff --git a/test/test-memmove_s.c b/test/test-memmove_s.c new file mode 100644 index 0000000000..6dc353783b --- /dev/null +++ b/test/test-memmove_s.c @@ -0,0 +1,65 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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_WANT_LIB_EXT1__ 1 +#include +#include +#include +#include + +#undef cur_handler +static constraint_handler_t cur_handler; + +constraint_handler_t *___pcur_handler(void) { + return &cur_handler; + } + +int main(void) +{ + char src[] = "ABCDEF"; + char dst[10]; + + errno_t err = memmove_s( dst, sizeof(dst), src, strlen(src)+1 ); + if (err == 0) + { + printf("memmove_s sucessful: %s\n", dst); + return 0; + } + else + { + printf("memmove_s failed: %s\n", strerror(err)); + return -1; + } +} \ No newline at end of file diff --git a/test/test-memset_s.c b/test/test-memset_s.c new file mode 100644 index 0000000000..acf693e46e --- /dev/null +++ b/test/test-memset_s.c @@ -0,0 +1,64 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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_WANT_LIB_EXT1__ 1 +#include +#include +#include +#include + +#undef cur_handler +static constraint_handler_t cur_handler; + +constraint_handler_t *___pcur_handler(void) { + return &cur_handler; + } + +int main(void) +{ + char dst[10]; + + errno_t err = memset_s( dst, sizeof(dst), 'X', sizeof(dst) ); + if (err == 0) + { + printf("memset_s sucessful: %s\n", dst); + return 0; + } + else + { + printf("memset_s failed: %s\n", strerror(err)); + return -1; + } +} \ No newline at end of file diff --git a/test/test-rsize_max_s.c b/test/test-rsize_max_s.c new file mode 100644 index 0000000000..1b34c7d20e --- /dev/null +++ b/test/test-rsize_max_s.c @@ -0,0 +1,80 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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_WANT_LIB_EXT1__ 1 +#include +#include +#include +#include +#include + +#undef cur_handler +static constraint_handler_t cur_handler; + +constraint_handler_t *___pcur_handler(void) { + return &cur_handler; + } + +int main(void) +{ + rsize_t current_max_size; + rsize_t new_max_size = 1024; + + // Get the current max size + current_max_size = _get_rsize_max_s(); + printf("Current max size: %zu bytes\n", current_max_size); + + // Set the max size to new value + errno_t err = _set_rsize_max_s(new_max_size); + if (err != 0) + { + printf("Error setting new max size: %s\n", strerror(err)); + } + + // Get the max size after setting it to new value + current_max_size = _get_rsize_max_s(); + printf("New max size: %zu bytes\n", current_max_size); + + if (current_max_size == 1024) + { + printf("Max size is correctly set to 1024 bytes.\n"); + return 0; + } + else + { + printf("Max size is not correctly set.\n"); + return -1; + } +} \ No newline at end of file diff --git a/test/test-sprintf_s.c b/test/test-sprintf_s.c new file mode 100644 index 0000000000..b38caa1c3b --- /dev/null +++ b/test/test-sprintf_s.c @@ -0,0 +1,66 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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_WANT_LIB_EXT1__ 1 +#include +#include +#include +#include + +#undef cur_handler +static constraint_handler_t cur_handler; + +constraint_handler_t *___pcur_handler(void) { + return &cur_handler; + } + +int main(void) +{ + char buf[20]; + int value = 123; + const char *text = "Hello"; + + errno_t err = sprintf_s(buf, sizeof(buf), "%s, value: %d", text, value); + if (err >= 0) + { + printf("Formatted string: %s\n", buf); + return 0; + } + else + { + printf("Error occurred: %d\n", err); + return -1; + } +} \ No newline at end of file diff --git a/test/test-strcat_s.c b/test/test-strcat_s.c new file mode 100644 index 0000000000..b8d3e7d772 --- /dev/null +++ b/test/test-strcat_s.c @@ -0,0 +1,65 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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_WANT_LIB_EXT1__ 1 +#include +#include +#include +#include + +#undef cur_handler +static constraint_handler_t cur_handler; + +constraint_handler_t *___pcur_handler(void) { + return &cur_handler; + } + +int main(void) +{ + const char *src = "world!"; + char dst[20] = "Hello "; + + errno_t err = strcat_s( dst, sizeof(dst), src ); + if (err == 0) + { + printf("strcat_s sucessful: %s\n", dst); + return 0; + } + else + { + printf("strcat_s failed: %s\n", strerror(err)); + return -1; + } +} \ No newline at end of file diff --git a/test/test-strcpy_s.c b/test/test-strcpy_s.c new file mode 100644 index 0000000000..e737645bbd --- /dev/null +++ b/test/test-strcpy_s.c @@ -0,0 +1,65 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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_WANT_LIB_EXT1__ 1 +#include +#include +#include +#include + +#undef cur_handler +static constraint_handler_t cur_handler; + +constraint_handler_t *___pcur_handler(void) { + return &cur_handler; + } + +int main(void) +{ + const char *src = "Hello world!"; + char dst[20]; + + errno_t err = strcpy_s( dst, sizeof(dst), src ); + if (err == 0) + { + printf("strcpy_s sucessful: %s\n", dst); + return 0; + } + else + { + printf("strcpy_s failed: %s\n", strerror(err)); + return -1; + } +} \ No newline at end of file diff --git a/test/test-strerror_s.c b/test/test-strerror_s.c new file mode 100644 index 0000000000..8a6aa095ec --- /dev/null +++ b/test/test-strerror_s.c @@ -0,0 +1,66 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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_WANT_LIB_EXT1__ 1 +#include +#include +#include +#include + +#undef cur_handler +static constraint_handler_t cur_handler; + +constraint_handler_t *___pcur_handler(void) { + return &cur_handler; + } + +int main(void) +{ + errno_t err = EINVAL; + + char buf[100]; + + int ret = strerror_s(buf, sizeof(buf), err); + if (ret == 0) + { + printf("Error message: %s\n", buf); + return 0; + } + else + { + printf("Error retrieving error message\n"); + return -1; + } +} \ No newline at end of file diff --git a/test/test-strerrorlen_s.c b/test/test-strerrorlen_s.c new file mode 100644 index 0000000000..262e623d45 --- /dev/null +++ b/test/test-strerrorlen_s.c @@ -0,0 +1,65 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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_WANT_LIB_EXT1__ 1 +#include +#include +#include +#include + +#undef cur_handler +static constraint_handler_t cur_handler; + +constraint_handler_t *___pcur_handler(void) { + return &cur_handler; + } + +int main(void) +{ + errno_t err = EINVAL; + + size_t length = strerrorlen_s(err); + + if (length != 0) + { + printf("Length of the error message: %zu\n", length); + return 0; + } + else + { + printf("Error retrieving error message length\n"); + return -1; + } +} \ No newline at end of file diff --git a/test/test-strncat_s.c b/test/test-strncat_s.c new file mode 100644 index 0000000000..d8a9c6eac9 --- /dev/null +++ b/test/test-strncat_s.c @@ -0,0 +1,65 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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_WANT_LIB_EXT1__ 1 +#include +#include +#include +#include + +#undef cur_handler +static constraint_handler_t cur_handler; + +constraint_handler_t *___pcur_handler(void) { + return &cur_handler; + } + +int main(void) +{ + char dst[20] = "Hello "; + const char *src = "world!"; + + errno_t err = strncat_s( dst, sizeof(dst), src, 5 ); + if (err == 0) + { + printf("strncat_s sucessful: %s\n", dst); + return 0; + } + else + { + printf("strncat_s failed: %s\n", strerror(err)); + return -1; + } +} \ No newline at end of file diff --git a/test/test-strncpy_s.c b/test/test-strncpy_s.c new file mode 100644 index 0000000000..3442728591 --- /dev/null +++ b/test/test-strncpy_s.c @@ -0,0 +1,65 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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_WANT_LIB_EXT1__ 1 +#include +#include +#include +#include + +#undef cur_handler +static constraint_handler_t cur_handler; + +constraint_handler_t *___pcur_handler(void) { + return &cur_handler; + } + +int main(void) +{ + const char *src = "Hello world!"; + char dst[20]; + + errno_t err = strncpy_s( dst, sizeof(dst), src, 5 ); + if (err == 0) + { + printf("strncpy_s sucessful: %s\n", dst); + return 0; + } + else + { + printf("strncpy_s failed: %s\n", strerror(err)); + return -1; + } +} \ No newline at end of file diff --git a/test/test-strnlen_s.c b/test/test-strnlen_s.c new file mode 100644 index 0000000000..5c76c80afc --- /dev/null +++ b/test/test-strnlen_s.c @@ -0,0 +1,56 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2024, Synopsys Inc. + * + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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_WANT_LIB_EXT1__ 1 +#include +#include +#include +#include + +#undef cur_handler +static constraint_handler_t cur_handler; + +constraint_handler_t *___pcur_handler(void) { + return &cur_handler; + } + +int main(void) +{ + const char *str = "Hello world!"; + + size_t length = strnlen_s( str, 20 ); + printf("Length of the string (up to 20 characters) : %zu\n", length); + return 0; +} \ No newline at end of file