diff options
authorAleksei Nikiforov <[email protected]>2017-10-29 12:51:16 +0100
committerAlbert Astals Cid <[email protected]>2017-10-29 12:51:47 +0100
commitdee0700a1f5aa5e362cd289e40aab3b263f42e02 (patch)
parent69f296d4d5b844833797c7a9b776efc2acb850d1 (diff)
Filelight crashes if readdir returns very long file name
Summary: While it's usually stated that 'struct dirent' has member 'char d_name[PATH_MAX + 1]', it is possible to obtain results when this field contains a string longer than PATH_MAX + 1. Stringbuilder in that case would copy only PATH_MAX + 1 first bytes, and wouldn't add zero terminator to this copied string, which would eventually lead to crash. How to reproduce: 1) use ntfs filesystem (for example, via ntfs-3g) Ntfs filesystem uses maximum number of characters for restricting file name length, not bytes, and character may be longer than 1 byte. 2) create a file with name out of > 255 bytes, but less than 255 characters. Use non-ascii characters for that and UTF-8 locale. It's too long filename for a Linux filesystem, but actually a valid name for ntfs filesystem. In my case, I hit a file with name of 166 characters and 264 bytes (not including zero terminator). 3) run filelight on filesystem containing that file and see it crash. What should happen: Filelight should run fine, and if struct dirent::d_name is longer that PATH_MAX, it should work fine with it. Reviewers: sitter, kfunk, sandsmark Reviewed By: sandsmark Subscribers: sandsmark, kde-utils-devel Differential Revision: https://phabricator.kde.org/D8413
1 files changed, 5 insertions, 1 deletions
diff --git a/src/localLister.cpp b/src/localLister.cpp
index 6a9a11e..68dc678 100644
--- a/src/localLister.cpp
+++ b/src/localLister.cpp
@@ -172,7 +172,11 @@ LocalLister::scan(const QByteArray &path, const QByteArray &dirname)
if (qstrcmp(ent->d_name, ".") == 0 || qstrcmp(ent->d_name, "..") == 0)
- QByteArray new_path = path + ent->d_name;
+ // QStringBuilder is used here. It assumes ent->d_name is char[NAME_MAX + 1],
+ // and thus copies only first NAME_MAX + 1 chars.
+ // Actually, while it's not fully POSIX-compatible, current behaviour may return d_name longer than NAME_MAX.
+ // Make full copy of this string.
+ QByteArray new_path = path + static_cast<const char*>(ent->d_name);
//get file information
if (lstat(new_path, &statbuf) == -1) {