diff --git a/newlib/libc/include/errno.h b/newlib/libc/include/errno.h index d52446d122..5e1081fa31 100644 --- a/newlib/libc/include/errno.h +++ b/newlib/libc/include/errno.h @@ -43,4 +43,9 @@ typedef int error_t; #include +#include +#ifdef __STDC_WANT_LIB_EXT1__ +typedef __errno_t errno_t; +#endif + #endif /* !__ERRNO_H__ */ diff --git a/newlib/libc/include/stdint.h b/newlib/libc/include/stdint.h index d7e9bf3666..7aeb7f0c0c 100644 --- a/newlib/libc/include/stdint.h +++ b/newlib/libc/include/stdint.h @@ -457,6 +457,17 @@ typedef __uint_least64_t uint_least64_t; #endif #endif +#if __STDC_WANT_LIB_EXT1__ == 1 + #include + + // could be defined by the user + #ifndef RSIZE_MAX + #define RSIZE_MAX SIZE_MAX + #endif + + typedef __rsize_t rsize_t; +#endif + _END_STD_C -#endif /* _STDINT_H */ +#endif /* _STDINT_H */ \ No newline at end of file diff --git a/newlib/libc/include/stdlib.h b/newlib/libc/include/stdlib.h index 7468be3a93..09c4dabc84 100644 --- a/newlib/libc/include/stdlib.h +++ b/newlib/libc/include/stdlib.h @@ -408,10 +408,24 @@ char *__ldtoa (long double, int, int, int *, int *, char **); void __eprintf (const char *, const char *, unsigned int, const char *); #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 __cur_handler; + +extern constraint_handler_t set_constraint_handler_s( + constraint_handler_t handler); +extern void abort_handler_s( + const char *restrict msg, void *restrict ptr, __errno_t error); +#endif + _END_STD_C #if __SSP_FORTIFY_LEVEL > 0 #include #endif -#endif /* _STDLIB_H_ */ +#endif /* _STDLIB_H_ */ \ No newline at end of file diff --git a/newlib/libc/include/string.h b/newlib/libc/include/string.h index d459f06bae..55c0d685fb 100644 --- a/newlib/libc/include/string.h +++ b/newlib/libc/include/string.h @@ -201,6 +201,24 @@ int timingsafe_bcmp (const void *, const void *, size_t); int timingsafe_memcmp (const void *, const void *, size_t); #endif + +#if __STDC_WANT_LIB_EXT1__ == 1 +#include + +typedef __rsize_t rsize_t; + +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 + #include _END_STD_C @@ -209,4 +227,4 @@ _END_STD_C #include #endif -#endif /* _STRING_H_ */ +#endif /* _STRING_H_ */ \ No newline at end of file diff --git a/newlib/libc/include/sys/_types.h b/newlib/libc/include/sys/_types.h index c38b7d1e60..5b42212a95 100644 --- a/newlib/libc/include/sys/_types.h +++ b/newlib/libc/include/sys/_types.h @@ -258,4 +258,22 @@ typedef unsigned short __nlink_t; typedef long __suseconds_t; /* microseconds (signed) */ typedef unsigned long __useconds_t; /* microseconds (unsigned) */ + +#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 + +#ifndef __RSIZE_T +#define __RSIZE_T +typedef size_t __rsize_t; +#endif + +typedef int __errno_t; + +#endif +#endif + #endif /* _SYS__TYPES_H */ diff --git a/newlib/libc/include/sys/errno.h b/newlib/libc/include/sys/errno.h index 7b0d8d33a9..e80929cf94 100644 --- a/newlib/libc/include/sys/errno.h +++ b/newlib/libc/include/sys/errno.h @@ -35,6 +35,7 @@ SUCH DAMAGE. #include #include +#include _BEGIN_STD_C @@ -52,7 +53,7 @@ _user_strerror (int errnum, #endif #ifdef __PICOLIBC_ERRNO_FUNCTION -int *__PICOLIBC_ERRNO_FUNCTION(void); +__errno_t *__PICOLIBC_ERRNO_FUNCTION(void); #define errno (*__PICOLIBC_ERRNO_FUNCTION()) #else extern NEWLIB_THREAD_LOCAL_ERRNO int errno; diff --git a/newlib/libc/stdlib/CMakeLists.txt b/newlib/libc/stdlib/CMakeLists.txt index 523243ba5f..8df4955c05 100644 --- a/newlib/libc/stdlib/CMakeLists.txt +++ b/newlib/libc/stdlib/CMakeLists.txt @@ -115,6 +115,7 @@ picolibc_sources( pico-exit.c pico-onexit.c pico-cxa-atexit.c + set_constraint_handler_s.c ) picolibc_sources_flags("-fno-builtin-malloc;-fno-builtin-free" diff --git a/newlib/libc/stdlib/meson.build b/newlib/libc/stdlib/meson.build index 2c31fd2c9b..fffe4c8398 100644 --- a/newlib/libc/stdlib/meson.build +++ b/newlib/libc/stdlib/meson.build @@ -161,6 +161,7 @@ srcs_stdlib = [ 'wctob.c', 'wctomb.c', 'wctomb_r.c', + 'set_constraint_handler_s.c', ] srcs_stdlib_stdio = [ 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..071cef6da3 --- /dev/null +++ b/newlib/libc/stdlib/set_constraint_handler_s.c @@ -0,0 +1,63 @@ +/* + * 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 + +constraint_handler_t __cur_handler = abort_handler_s; + +void abort_handler_s(const char *restrict msg, void *restrict ptr, __errno_t error) +{ + (void) msg; + (void) ptr; + (void) error; + abort(); +} + +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 = abort_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 d31976e928..48ce38aa5c 100644 --- a/newlib/libc/string/CMakeLists.txt +++ b/newlib/libc/string/CMakeLists.txt @@ -135,4 +135,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..a5a79822e5 --- /dev/null +++ b/newlib/libc/string/memcpy_s.c @@ -0,0 +1,106 @@ +/* + * 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) +{ + const char* msg = ""; + constraint_handler_t handler = NULL; + + if (s1 == NULL) + { + msg = "memcpy_s: dest is NULL"; + goto handle_error; + } + + if (s1max > RSIZE_MAX) + { + msg = "memcpy_s: buffer size exceeds RSIZE_MAX"; + goto handle_error; + } + + if (s2 == NULL) + { + msg = "memcpy_s: source is NULL"; + goto handle_error; + } + + if (n > RSIZE_MAX) + { + msg = "memcpy_s: copy count exceeds RSIZE_MAX"; + goto handle_error; + } + + if (n > s1max) + { + msg = "memcpy_s: copy count exceeds buffer size"; + goto handle_error; + } + + 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) + { + msg = "memcpy_s: overlapping copy"; + goto handle_error; + } + + // Normal return path + (void) memcpy(s1, s2, n); + return 0; + +handle_error: + handler = set_constraint_handler_s(NULL); + (void) set_constraint_handler_s(handler); + + if (s1 != NULL) + { + (void) memset(s1, (int32_t)'\0', s1max); + } + + if (handler != NULL) + { + handler(msg, NULL, -1); + } + + return -1; +} diff --git a/newlib/libc/string/memmove_s.c b/newlib/libc/string/memmove_s.c new file mode 100644 index 0000000000..bc82347505 --- /dev/null +++ b/newlib/libc/string/memmove_s.c @@ -0,0 +1,98 @@ +/* + * 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) +{ + const char* msg = ""; + constraint_handler_t handler = NULL; + + if (s1 == NULL) + { + msg = "memmove_s: dest is NULL"; + goto handle_error; + } + + if (s1max > RSIZE_MAX) + { + msg = "memmove_s: buffer size exceeds RSIZE_MAX"; + goto handle_error; + } + + if (s2 == NULL) + { + msg = "memmove_s: source is NULL"; + goto handle_error; + } + + if (n > RSIZE_MAX) + { + msg = "memmove_s: copy count exceeds RSIZE_MAX"; + goto handle_error; + } + + if (n > s1max) + { + msg = "memmove_s: copy count exceeds buffer size"; + goto handle_error; + } + + /* overlapping memory is allowed for memmove_s so no checks for that */ + + + // Normal return path + (void) memmove(s1, s2, n); + return 0; + +handle_error: + handler = set_constraint_handler_s(NULL); + (void) set_constraint_handler_s(handler); + + if (s1 != NULL) + { + (void) memset(s1, (int32_t)'\0', s1max); + } + + if (handler != NULL) + { + handler(msg, NULL, -1); + } + + return -1; +} diff --git a/newlib/libc/string/memset_s.c b/newlib/libc/string/memset_s.c new file mode 100644 index 0000000000..f907f1c815 --- /dev/null +++ b/newlib/libc/string/memset_s.c @@ -0,0 +1,89 @@ +/* + * 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) +{ + const char* msg = ""; + constraint_handler_t handler = NULL; + + if (s == NULL) + { + msg = "memset_s: dest is NULL"; + goto handle_error; + } + + if (smax > RSIZE_MAX) + { + msg = "memset_s: buffer size exceeds RSIZE_MAX"; + goto handle_error; + } + + if (n > RSIZE_MAX) + { + msg = "memset_s: count exceeds RSIZE_MAX"; + goto handle_error; + } + + if (n > smax) + { + msg = "memset_s: count exceeds buffer size"; + goto handle_error; + } + + // Normal return path + (void) memset(s, c, n); + return 0; + +handle_error: + handler = set_constraint_handler_s(NULL); + (void) set_constraint_handler_s(handler); + + if (s != NULL) + { + (void) memset(s, c, smax); + } + + if (handler != NULL) + { + handler(msg, NULL, -1); + } + + return -1; +} diff --git a/newlib/libc/string/meson.build b/newlib/libc/string/meson.build index 9aac49ea23..e7e9f264ce 100644 --- a/newlib/libc/string/meson.build +++ b/newlib/libc/string/meson.build @@ -134,11 +134,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..8559d67679 --- /dev/null +++ b/newlib/libc/string/strcat_s.c @@ -0,0 +1,163 @@ +/* + * 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) +{ + const char *msg = ""; + size_t s1_len = 0; + bool write_null = true; + constraint_handler_t handler = NULL; + + if (s1 == NULL) + { + msg = "strcat_s: dest is NULL"; + write_null = false; + goto handle_error; + } + + if (s1max == 0 || s1max > RSIZE_MAX) + { + msg = "strcat_s: dest buffer size is 0 or exceeds RSIZE_MAX"; + write_null = false; + goto handle_error; + } + + if (s2 == NULL) + { + msg = "strcat_s: source is NULL"; + goto handle_error; + } + + /* 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. + */ + // compute chars available in s1 + s1_len = strnlen_s(s1, s1max); + if (s1_len == s1max) + { + msg = "strcat_s: string 1 length exceeds buffer size"; + goto handle_error; + } + + const char *overlap_point; + bool check_s1_for_overlap; + unsigned m = s1max - s1_len; + char *s1cp = s1 + s1_len; + 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) + { + msg = "strcat_s: overlapping copy"; + goto handle_error; + } + } + 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. + } + + unsigned written = 0; + char c = '.'; + while (written < m) + { + if (check_s1_for_overlap) + { + if (s1cp == overlap_point) + { + msg = "strcat_s: overlapping copy"; + goto handle_error; + } + } + else if (s2cp == overlap_point) + { + msg = "strcat_s: overlapping copy"; + goto handle_error; + } + + c = *s2cp++; + *s1cp++ = c; + written++; + if (c == '\0') + { + break; + } + } + + if (c != '\0') + { + msg = "strcat_s: dest buffer size insufficent to append string"; + goto handle_error; + } + + // Normal return path + return 0; + +handle_error: + handler = set_constraint_handler_s(NULL); + set_constraint_handler_s(handler); + + if (write_null && s1 != NULL) + { + *s1 = '\0'; + } + + if (handler != NULL) + { + handler(msg, NULL, -1); + } + + return -1; +} diff --git a/newlib/libc/string/strcpy_s.c b/newlib/libc/string/strcpy_s.c new file mode 100644 index 0000000000..c496f34918 --- /dev/null +++ b/newlib/libc/string/strcpy_s.c @@ -0,0 +1,145 @@ +/* + * 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) +{ + const char *msg = ""; + bool write_null = true; + constraint_handler_t handler = NULL; + + if (s1 == NULL) + { + msg = "strcpy_s: dest is NULL"; + write_null = false; + goto handle_error; + } + + if (s1max == 0 || s1max > RSIZE_MAX) + { + msg = "strcpy_s: dest buffer size is 0 or exceeds RSIZE_MAX"; + write_null = false; + goto handle_error; + } + + if (s2 == NULL) + { + msg = "strcpy_s: source is NULL"; + goto handle_error; + } + + /* 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. + */ + 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) + { + msg = "strcpy_s: overlapping copy"; + goto handle_error; + } + } + else if (s2cp == overlap_point) + { + msg = "strcpy_s: overlapping copy"; + goto handle_error; + } + + c = *s2cp++; + *s1cp++ = c; + written++; + if (c == '\0') + { + break; + } + + } + + if (c != '\0') + { + msg = "strcpy_s: dest buffer size insufficent to copy string"; + goto handle_error; + } + + // Normal return path + return 0; + +handle_error: + handler = set_constraint_handler_s(NULL); + set_constraint_handler_s(handler); + + if (write_null && s1 != NULL) + { + *s1 = '\0'; + } + + if (handler != NULL) + { + handler(msg, NULL, -1); + } + + return -1; +} diff --git a/newlib/libc/string/strerror.c b/newlib/libc/string/strerror.c index 5788505b1b..9c3e38191d 100644 --- a/newlib/libc/string/strerror.c +++ b/newlib/libc/string/strerror.c @@ -400,6 +400,7 @@ QUICKREF #define _DEFAULT_SOURCE #include #include +#include "string_private.h" #include "local.h" extern char *_user_strerror (int, int, int *) _ATTRIBUTE((__weak__)); diff --git a/newlib/libc/string/strerror_s.c b/newlib/libc/string/strerror_s.c new file mode 100644 index 0000000000..7eab21bd1a --- /dev/null +++ b/newlib/libc/string/strerror_s.c @@ -0,0 +1,98 @@ +/* + * 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" + +/* 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; + const char *msg = ""; + constraint_handler_t handler = NULL; + + + if (buf == NULL) + { + msg = "strerror_s: dest is NULL"; + goto handle_error; + } + + if ((buflen == 0u) || (buflen > RSIZE_MAX)) + { + msg = "strerror_s: dest buffer size is 0 or exceeds RSIZE_MAX"; + goto handle_error; + } + + const char *cp = _strerror_r(errnum, 0, NULL); + 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; + } + + // Normal return path + return result; + +handle_error: + handler = set_constraint_handler_s(NULL); + (void)set_constraint_handler_s(handler); + + if (handler != NULL) + { + handler(msg, NULL, -1); + } + + return -1; +} diff --git a/newlib/libc/string/strerrorlen_s.c b/newlib/libc/string/strerrorlen_s.c new file mode 100644 index 0000000000..450b27e7fa --- /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(_strerror_r(errnum, 0, NULL), 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..720698973c --- /dev/null +++ b/newlib/libc/string/string_private.h @@ -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. + */ +#ifndef STRING_PRIVATE_H_ +#define STRING_PRIVATE_H_ + +#define MAX_ERROR_MSG 50 + +char *_strerror_r (int errnum, int internal, int *errptr); + +#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..22e391acce --- /dev/null +++ b/newlib/libc/string/strncat_s.c @@ -0,0 +1,204 @@ +/* + * 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) +{ + const char *msg = ""; + size_t s1_len = 0; + bool write_null = true; + constraint_handler_t handler = NULL; + + s1_len = strnlen_s(s1, s1max); + + if (s1 == NULL) + { + msg = "strncat_s: dest is NULL"; + write_null = false; + goto handle_error; + } + else if ( (s1max == 0u) || (s1max > RSIZE_MAX)) + { + msg = "strncat_s: dest buffer size is 0 or exceeds RSIZE_MAX"; + write_null = false; + goto handle_error; + } + else if (s2 == NULL) + { + msg = "strncat_s: source is NULL"; + goto handle_error; + } + else if (n > RSIZE_MAX) + { + msg = "strncat_s: copy count exceeds RSIZE_MAX"; + goto handle_error; + } + + /* 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) + { + msg = "strcat_s: string 1 length exceeds buffer size"; + goto handle_error; + } + 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) + { + msg = "strcat_s: overlapping copy"; + goto handle_error; + } + } + 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) + { + msg = "strncat_s: overlapping copy"; + goto handle_error; + } + } + else if (s2cp == overlap_point) + { + msg = "strncat_s: overlapping copy"; + goto handle_error; + } + else + { + /* Normal case*/ + } + + c = *s2cp; + s2cp++; + *s1cp = c; + s1cp++; + written++; + + if (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)) + { + msg = "strncat_s: overlapping copy"; + goto handle_error; + } + else + { + c = '\0'; + *s1cp = '\0'; + } + } + + if (c != '\0') + { + msg = "strncat_s: dest buffer size insufficent to copy string"; + goto handle_error; + } + } + + // Normal return path + return 0; + +handle_error: + handler = set_constraint_handler_s(NULL); + (void)set_constraint_handler_s(handler); + + if (write_null && s1 != NULL) + { + *s1 = '\0'; + } + + if (handler != NULL) + { + handler(msg, NULL, -1); + } + + return -1; +} diff --git a/newlib/libc/string/strncpy_s.c b/newlib/libc/string/strncpy_s.c new file mode 100644 index 0000000000..5f6aa5de06 --- /dev/null +++ b/newlib/libc/string/strncpy_s.c @@ -0,0 +1,178 @@ +/* + * 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) +{ + const char *msg = ""; + bool write_null = true; + constraint_handler_t handler = NULL; + + if (s1 == NULL) + { + msg = "strncpy_s: dest is NULL"; + write_null = false; + goto handle_error; + } + else if ((s1max == 0u) || (s1max > RSIZE_MAX)) + { + msg = "strncpy_s: dest buffer size is 0 or exceeds RSIZE_MAX"; + write_null = false; + goto handle_error; + } + + else if (s2 == NULL) + { + msg = "strncpy_s: source is NULL"; + goto handle_error; + } + else if (n > RSIZE_MAX) + { + msg = "strncpy_s: copy count exceeds RSIZE_MAX"; + goto handle_error; + } + + /* 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) + { + msg = "strncpy_s: overlapping copy"; + goto handle_error; + } + } + else if (s2cp == overlap_point) + { + msg = "strncpy_s: overlapping copy"; + goto handle_error; + } + else + { + /* Normal case*/ + } + + c = *s2cp; + s2cp++; + *s1cp = c; + s1cp++; + written++; + + if (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)) + { + msg = "strncpy_s: overlapping copy"; + goto handle_error; + } + else + { + c = '\0'; + *s1cp = '\0'; + } + } + + if (c != '\0') + { + msg = "strncpy_s: dest buffer size insufficent to copy string"; + goto handle_error; + } + + } + + // Normal return path + return 0; + +handle_error: + handler = set_constraint_handler_s(NULL); + (void)set_constraint_handler_s(handler); + + if (write_null && s1 != NULL) + { + *s1 = '\0'; + } + + if (handler != NULL) + { + handler(msg, NULL, -1); + } + + return -1; +} 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 71f6318d16..97077ac6c5 100644 --- a/newlib/libc/tinystdio/CMakeLists.txt +++ b/newlib/libc/tinystdio/CMakeLists.txt @@ -166,6 +166,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 8c5c8b40de..0f45fe0ec2 100644 --- a/newlib/libc/tinystdio/meson.build +++ b/newlib/libc/tinystdio/meson.build @@ -169,6 +169,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..58c393188a --- /dev/null +++ b/newlib/libc/tinystdio/sprintf_s.c @@ -0,0 +1,154 @@ +/* + * 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 + +int sprintf_s(char *restrict s, rsize_t bufsize, + const char * restrict fmt, ...) { + bool write_null = true; + const char *msg = ""; + va_list args; + int rc; + constraint_handler_t handler = NULL; + + if (s == NULL) + { + write_null = false; + msg = "sprintf_s: dest buffer is null"; + goto handle_error; + } + else if (bufsize == 0 || bufsize > RSIZE_MAX) + { + write_null = false; + msg = "sprintf_s: invalid buffer size"; + goto handle_error; + } + else if (fmt == NULL) + { + msg = "sprintf_s: null format string"; + goto handle_error; + } + else if (strstr(fmt, " %n") != NULL) + { + msg = "sprintf_s: format string contains percent-n"; + goto handle_error; + } + 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) + { + msg = "sprintf_s: null string argument"; + va_end(args_copy); + va_end(args); + null_str = 1; + goto handle_error; + } + 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++; + } + + rc = vsnprintf(s, bufsize, fmt, args); + va_end(args_copy); + va_end(args); + } + + if (rc < 0 || rc >= (int)bufsize) + { + msg = "sprintf_s: dest buffer overflow"; + goto handle_error; + } + else + { + s[rc] = 0; + } + + // Normal return path + return rc; + +handle_error: + handler = set_constraint_handler_s(NULL); + (void) set_constraint_handler_s(handler); + + if (handler != NULL) + { + handler(msg, NULL, -1); + } + + rc = 0; /* standard stipulates this */ + + if (write_null && s != 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 0b2c92e2db..723a77d0aa 100644 --- a/newlib/libc/tinystdio/stdio.h +++ b/newlib/libc/tinystdio/stdio.h @@ -375,6 +375,15 @@ int putchar_unlocked (int); #define putchar_unlocked(c, f) fgetc(c, stdin) #endif +#if __STDC_WANT_LIB_EXT1__ == 1 +#include + +typedef __rsize_t rsize_t; + +extern int sprintf_s(char *__restrict __s, rsize_t __bufsize, + const char *__restrict __format, ...); +#endif + /* * The format of tmpnam names is TXXXXXX, which works with mktemp */ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index da55c79760..3fc61f4594 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -61,6 +61,17 @@ set(tests test-sprintf-percent-n 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-sprintf_s ) set(tests_fail diff --git a/test/meson.build b/test/meson.build index 8ddd9666a2..b8c0ecb9c1 100644 --- a/test/meson.build +++ b/test/meson.build @@ -583,6 +583,71 @@ foreach target : targets timeout: 60, env: test_env) + plain_tests = ['rand', 'regex', 'ungetc', 'fenv', + 'malloc', 'tls', + 'ffs', 'setjmp', 'atexit', 'on_exit', + 'math-funcs', 'timegm', 'time-tests', + 'test-strtod', 'test-strchr', + 'test-memset', 'test-put', + 'test-efcvt', 'test-atomic', + 'test-raise', + 'test-fma', + 'test-funopen', + ] + + if have_attr_ctor_dtor + plain_tests += 'constructor' + endif + + if have_complex + plain_tests += 'complex-funcs' + endif + + if newlib_nano_malloc or tests_enable_full_malloc_stress + plain_tests += 'malloc_stress' + endif + + if tinystdio + plain_tests += 't_fmemopen' + endif + + if (posix_io or not tinystdio) and tests_enable_posix_io + plain_tests += ['posix-io'] + + # legacy stdio doesn't work on semihosting, so just skip it + if tinystdio + plain_tests += ['test-fopen', + 'test-mktemp', + 'test-tmpnam', + 'test-fread-fwrite', + 'test-ungetc-ftell', + 'test-fgetc', + 'test-fgets-eof', + ] + endif + endif + + if tests_enable_stack_protector + 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', + ] + + 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..84e2afc874 --- /dev/null +++ b/test/test-memcpy_s.c @@ -0,0 +1,58 @@ +/* + * 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 + +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..b357b36907 --- /dev/null +++ b/test/test-memmove_s.c @@ -0,0 +1,58 @@ +/* + * 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 + +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..5d50fc3e70 --- /dev/null +++ b/test/test-memset_s.c @@ -0,0 +1,57 @@ +/* + * 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 + +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-sprintf_s.c b/test/test-sprintf_s.c new file mode 100644 index 0000000000..6e91b9f66a --- /dev/null +++ b/test/test-sprintf_s.c @@ -0,0 +1,59 @@ +/* + * 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 + +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..73a970226b --- /dev/null +++ b/test/test-strcat_s.c @@ -0,0 +1,58 @@ +/* + * 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 + +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..c0df9023a2 --- /dev/null +++ b/test/test-strcpy_s.c @@ -0,0 +1,58 @@ +/* + * 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 + +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..af089f8e32 --- /dev/null +++ b/test/test-strerror_s.c @@ -0,0 +1,59 @@ +/* + * 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 + +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..4b4d965aab --- /dev/null +++ b/test/test-strerrorlen_s.c @@ -0,0 +1,58 @@ +/* + * 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 + +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..38f941f085 --- /dev/null +++ b/test/test-strncat_s.c @@ -0,0 +1,58 @@ +/* + * 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 + +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..5f2b686660 --- /dev/null +++ b/test/test-strncpy_s.c @@ -0,0 +1,58 @@ +/* + * 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 + +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..b40f6cddd4 --- /dev/null +++ b/test/test-strnlen_s.c @@ -0,0 +1,49 @@ +/* + * 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 + +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