[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [kio] src/ioslaves/file: Sanitize the symlink name buffer size.
From:       Andreas Hartmetz <ahartmetz () gmail ! com>
Date:       2016-10-29 19:14:03
Message-ID: E1c0Z4t-00052j-Ox () code ! kde ! org
[Download RAW message or body]

Git commit 44512b6acbe6bb1c595e330bef702a0100d7bd4b by Andreas Hartmetz, on behalf of Taro Yamada.
Committed on 29/10/2016 at 19:13.
Pushed by ahartmetz into branch 'master'.

Sanitize the symlink name buffer size.

Currently, KIO uses lstat to get the buffersize for readlink.
But in certain situations, it returns an inappropriate value.

For example, "/proc/self" or "/sys/bus/cpu/devices/*" returns
its size is 0, and then readlink fails with EINVAL (so the
link won't be shown in KDE applications). TMSU seems to return
the target's actual filesize instead of the link size,
i.e. the length of the target's filename.

This patch limits the initial buffer size to sane values and
expands the buffer when needed. The behavior is similar to
ls, so it should be compatible with all filesystems.

REVIEW: 129259
BUG: 369275

M  +16   -6    src/ioslaves/file/file.cpp

http://commits.kde.org/kio/44512b6acbe6bb1c595e330bef702a0100d7bd4b

diff --git a/src/ioslaves/file/file.cpp b/src/ioslaves/file/file.cpp
index 8b17d31..9728465 100644
--- a/src/ioslaves/file/file.cpp
+++ b/src/ioslaves/file/file.cpp
@@ -786,13 +786,23 @@ bool FileProtocol::createUDSEntry(const QString &filename, const QByteArray &pat
             const QString linkTarget = QFile::symLinkTarget(QFile::decodeName(path));
 #else
             // Use readlink on Unix because symLinkTarget turns relative targets into absolute (#352927)
-            QByteArray linkTargetBuffer;
-            linkTargetBuffer.resize(buff.st_size);
-            const int n = readlink(path.constData(), linkTargetBuffer.data(), buff.st_size);
-            if (n == -1) {
-                qWarning() << "readlink failed!" << path;
-                return false;
+            ssize_t n;
+            const off_t lowerLimit = 1;
+            const off_t upperLimit = 1024;
+            size_t bufferSize = qBound(lowerLimit, buff.st_size , upperLimit);
+            QByteArray linkTargetBuffer(bufferSize, '\0');
+            while (true) {
+                n = readlink(path.constData(), linkTargetBuffer.data(), bufferSize);
+                if (n < 0 && errno != ERANGE) {
+                    qWarning() << "readlink failed!" << path;
+                    return false;
+                } else if (n > 0 && static_cast<size_t>(n) != bufferSize) {
+                    break;
+                }
+                bufferSize *= 2;
+                linkTargetBuffer.resize(bufferSize);
             }
+            linkTargetBuffer.truncate(n);
             const QString linkTarget = QFile::decodeName(linkTargetBuffer);
 #endif
             entry.insert(KIO::UDSEntry::UDS_LINK_DEST, linkTarget);
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic