From f18d6610d364bea6f96d954a74939371c42d2de3 Mon Sep 17 00:00:00 2001 From: Sergey Bugaev Date: Tue, 14 Apr 2020 18:39:56 +0300 Subject: [PATCH] Kernel: Don't include null terminator in sys$readlink() result POSIX says, "Conforming applications should not assume that the returned contents of the symbolic link are null-terminated." If we do include the null terminator into the returning string, Python believes it to actually be a part of the returned name, and gets unhappy about that later. This suggests other systems Python runs in don't include it, so let's do that too. Also, make our userspace support non-null-terminated realpath(). --- Applications/FileManager/PropertiesDialog.cpp | 5 +++-- Kernel/Process.cpp | 6 +++--- Userland/ls.cpp | 8 +++++--- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Applications/FileManager/PropertiesDialog.cpp b/Applications/FileManager/PropertiesDialog.cpp index 97866016b0c..10b89509148 100644 --- a/Applications/FileManager/PropertiesDialog.cpp +++ b/Applications/FileManager/PropertiesDialog.cpp @@ -108,10 +108,11 @@ PropertiesDialog::PropertiesDialog(GUI::FileSystemModel& model, String path, boo if (S_ISLNK(m_mode)) { char link_destination[PATH_MAX]; - if (readlink(path.characters(), link_destination, sizeof(link_destination)) < 0) { + ssize_t len = readlink(path.characters(), link_destination, sizeof(link_destination)); + if (len < 0) { perror("readlink"); } else { - properties.append({ "Link target:", link_destination }); + properties.append({ "Link target:", String(link_destination, len) }); } } diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 0470e5f3fc4..23709611f7f 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -1950,10 +1950,10 @@ int Process::sys$readlink(const Syscall::SC_readlink_params* user_params) return -EIO; // FIXME: Get a more detailed error from VFS. auto link_target = String::copy(contents); - if (link_target.length() + 1 > params.buffer.size) + if (link_target.length() > params.buffer.size) return -ENAMETOOLONG; - copy_to_user(params.buffer.data, link_target.characters(), link_target.length() + 1); - return link_target.length() + 1; + copy_to_user(params.buffer.data, link_target.characters(), link_target.length()); + return link_target.length(); } int Process::sys$chdir(const char* user_path, size_t path_length) diff --git a/Userland/ls.cpp b/Userland/ls.cpp index 596ffd774e1..b567356fcee 100644 --- a/Userland/ls.cpp +++ b/Userland/ls.cpp @@ -176,11 +176,13 @@ size_t print_name(const struct stat& st, const String& name, const char* path_fo if (S_ISLNK(st.st_mode)) { if (path_for_link_resolution) { char linkbuf[PATH_MAX]; - ssize_t nread = readlink(path_for_link_resolution, linkbuf, sizeof(linkbuf)); - if (nread < 0) + ssize_t nread = readlink(path_for_link_resolution, linkbuf, sizeof(linkbuf) - 1); + if (nread < 0) { perror("readlink failed"); - else + } else { + linkbuf[nread] = '\0'; nprinted += printf(" -> ") + print_escaped(linkbuf); + } } else { nprinted += printf("@"); }