Fix QDir::mkpath() when the path contains "symlink/../"
It is incorrect to collapse a "symlink/.." segment because the parent directory of the symlink's target may not be the directory where the symlink itself is located. [ChangeLog][QtCore][QDir] Fixed a bug that caused QDir::mkpath() to create the wrong directory if the requested path contained a symbolic link and "../". Change-Id: Iaddbecfbba5441c8b2e4fffd14a3e367730a1e24 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@qt.io> Reviewed-by: David Faure <david.faure@kdab.com>
This commit is contained in:
parent
49163ca689
commit
23d08ce2ed
@ -1,5 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 Intel Corporation.
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
@ -603,25 +604,7 @@ bool QFileSystemEngine::createDirectory(const QFileSystemEntry &entry, bool crea
|
||||
if (!createParents)
|
||||
return false;
|
||||
|
||||
// we need the cleaned path in order to create the parents
|
||||
// and we save errno just in case encodeName needs to load codecs
|
||||
int savedErrno = errno;
|
||||
bool pathChanged;
|
||||
{
|
||||
QString cleanName = QDir::cleanPath(dirName);
|
||||
|
||||
// Check if the cleaned name is the same or not. If we were given a
|
||||
// path with resolvable "../" sections, cleanPath will remove them, but
|
||||
// this may change the target dir if one of those segments was a
|
||||
// symlink. This operation depends on cleanPath's optimization of
|
||||
// returning the original string if it didn't modify anything.
|
||||
pathChanged = !dirName.isSharedWith(cleanName);
|
||||
if (pathChanged)
|
||||
nativeName = QFile::encodeName(cleanName);
|
||||
}
|
||||
|
||||
errno = savedErrno;
|
||||
return createDirectoryWithParents(nativeName, pathChanged);
|
||||
return createDirectoryWithParents(nativeName, false);
|
||||
}
|
||||
|
||||
//static
|
||||
|
@ -1,5 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 Intel Corporation.
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
@ -101,6 +102,7 @@ private slots:
|
||||
|
||||
void mkdirRmdir_data();
|
||||
void mkdirRmdir();
|
||||
void mkdirOnSymlink();
|
||||
|
||||
void makedirReturnCode();
|
||||
|
||||
@ -387,6 +389,56 @@ void tst_QDir::mkdirRmdir()
|
||||
QVERIFY(!fi.exists());
|
||||
}
|
||||
|
||||
void tst_QDir::mkdirOnSymlink()
|
||||
{
|
||||
#ifndef Q_OS_UNIX
|
||||
QSKIP("Test only valid on an OS that supports symlinks");
|
||||
#else
|
||||
// Create the structure:
|
||||
// .
|
||||
// ├── symlink -> two/three
|
||||
// └── two
|
||||
// └── three
|
||||
// so when we mkdir("symlink/../four/five"), we end up with:
|
||||
// .
|
||||
// ├── symlink -> two/three
|
||||
// └── two
|
||||
// ├── four
|
||||
// │ └── five
|
||||
// └── three
|
||||
|
||||
QDir dir;
|
||||
struct Clean {
|
||||
QDir &dir;
|
||||
Clean(QDir &dir) : dir(dir) {}
|
||||
~Clean() { doClean(); }
|
||||
void doClean() {
|
||||
dir.rmpath("two/three");
|
||||
dir.rmpath("two/four/five");
|
||||
// in case the test fails, don't leave junk behind
|
||||
dir.rmpath("four/five");
|
||||
QFile::remove("symlink");
|
||||
}
|
||||
};
|
||||
Clean clean(dir);
|
||||
clean.doClean();
|
||||
|
||||
// create our structure:
|
||||
dir.mkpath("two/three");
|
||||
::symlink("two/three", "symlink");
|
||||
|
||||
// try it:
|
||||
QString path = "symlink/../four/five";
|
||||
QVERIFY(dir.mkpath(path));
|
||||
QFileInfo fi(path);
|
||||
QVERIFY2(fi.exists() && fi.isDir(), msgDoesNotExist(path).constData());
|
||||
|
||||
path = "two/four/five";
|
||||
fi.setFile(path);
|
||||
QVERIFY2(fi.exists() && fi.isDir(), msgDoesNotExist(path).constData());
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QDir::makedirReturnCode()
|
||||
{
|
||||
QString dirName = QString::fromLatin1("makedirReturnCode");
|
||||
|
Loading…
Reference in New Issue
Block a user