diff options
-rw-r--r-- | Tests/LibC/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Tests/LibC/TestLibCString.cpp | 18 | ||||
-rw-r--r-- | Userland/Libraries/LibC/string.cpp | 20 | ||||
-rw-r--r-- | Userland/Libraries/LibC/string.h | 1 |
4 files changed, 40 insertions, 0 deletions
diff --git a/Tests/LibC/CMakeLists.txt b/Tests/LibC/CMakeLists.txt index d18144aff4..a4f8a4ce0b 100644 --- a/Tests/LibC/CMakeLists.txt +++ b/Tests/LibC/CMakeLists.txt @@ -6,6 +6,7 @@ set(TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/TestLibCExec.cpp ${CMAKE_CURRENT_SOURCE_DIR}/TestLibCDirEnt.cpp ${CMAKE_CURRENT_SOURCE_DIR}/TestLibCInodeWatcher.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TestLibCString.cpp ) file(GLOB CMD_SOURCES CONFIGURE_DEPENDS "*.cpp") diff --git a/Tests/LibC/TestLibCString.cpp b/Tests/LibC/TestLibCString.cpp new file mode 100644 index 0000000000..57ff705657 --- /dev/null +++ b/Tests/LibC/TestLibCString.cpp @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2021, Gunnar Beutner <gbeutner@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <LibTest/TestCase.h> +#include <errno.h> +#include <string.h> + +TEST_CASE(strerror_r_basic) +{ + EXPECT_EQ(strerror_r(1000, nullptr, 0), EINVAL); + EXPECT_EQ(strerror_r(EFAULT, nullptr, 0), ERANGE); + char buf[64]; + EXPECT_EQ(strerror_r(EFAULT, buf, sizeof(buf)), 0); + EXPECT_EQ(strcmp(buf, "Bad address"), 0); +} diff --git a/Userland/Libraries/LibC/string.cpp b/Userland/Libraries/LibC/string.cpp index db74946ae8..3847afb6dc 100644 --- a/Userland/Libraries/LibC/string.cpp +++ b/Userland/Libraries/LibC/string.cpp @@ -354,6 +354,26 @@ const char* const sys_errlist[] = { int sys_nerr = EMAXERRNO; +int strerror_r(int errnum, char* buf, size_t buflen) +{ + auto saved_errno = errno; + if (errnum >= EMAXERRNO) { + auto rc = strlcpy(buf, "unknown error", buflen); + if (rc >= buflen) + dbgln("strerror_r(): Invalid error number '{}' specified and the output buffer is too small.", errnum); + errno = saved_errno; + return EINVAL; + } + auto text = strerror(errnum); + auto rc = strlcpy(buf, text, buflen); + if (rc >= buflen) { + errno = saved_errno; + return ERANGE; + } + errno = saved_errno; + return 0; +} + char* strerror(int errnum) { if (errnum < 0 || errnum >= EMAXERRNO) { diff --git a/Userland/Libraries/LibC/string.h b/Userland/Libraries/LibC/string.h index beaf594a33..d7010ef6ac 100644 --- a/Userland/Libraries/LibC/string.h +++ b/Userland/Libraries/LibC/string.h @@ -43,6 +43,7 @@ char* strncat(char* dest, const char* src, size_t); size_t strspn(const char*, const char* accept); size_t strcspn(const char*, const char* reject); +int strerror_r(int, char*, size_t); char* strerror(int errnum); char* strsignal(int signum); char* strpbrk(const char*, const char* accept); |