summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Tests/LibC/CMakeLists.txt1
-rw-r--r--Tests/LibC/TestLibCString.cpp18
-rw-r--r--Userland/Libraries/LibC/string.cpp20
-rw-r--r--Userland/Libraries/LibC/string.h1
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);