File Ensure-extraction-location-to-be-in-subfolder.patch of Package karchive.openSUSE_Leap_42.1_Update
From: Andreas Cord-Landwehr <cordlandwehr@kde.org>
Date: Tue, 14 Jun 2016 13:52:49 +0000
Subject: Ensure extraction location to be in subfolder
X-Git-Tag: v5.24.0
X-Git-Url: http://quickgit.kde.org/?p=karchive.git&a=commitdiff&h=0cb243f64eef45565741b27364cece7d5c349c37
---
Ensure extraction location to be in subfolder
Behavior change: Switch to Tar's default behavior to avoid extraction
to arbitrary system locations outside of extraction folder. Instead,
extract such files to root location in extraction folder.
REVIEW: 128185
---
--- a/autotests/karchivetest.cpp
+++ b/autotests/karchivetest.cpp
@@ -759,6 +759,24 @@
QVERIFY(listing[2].contains("path=d/f2.txt"));
QCOMPARE(listing.count(), 3);
+}
+
+void KArchiveTest::testTarIgnoreRelativePathOutsideArchive()
+{
+ // This test extracts a Tar archive that contains a relative path "../foo" pointing
+ // outside of the archive directory. For security reasons extractions should only
+ // be allowed within the extracted directory as long as not specifically asked.
+
+ KTar tar(QFINDTESTDATA(QLatin1String("tar_relative_path_outside_archive.tar.bz2")));
+ QVERIFY(tar.open(QIODevice::ReadOnly));
+
+ const KArchiveDirectory *dir = tar.directory();
+ QTemporaryDir tmpDir;
+ const QString dirName = tmpDir.path() + '/';
+
+ QVERIFY(dir->copyTo(dirName));
+ QVERIFY(!QFile::exists(dirName + "../foo"));
+ QVERIFY(QFile::exists(dirName + "/foo"));
}
///
--- a/autotests/karchivetest.h
+++ b/autotests/karchivetest.h
@@ -76,6 +76,7 @@
void testTarDirectoryForgotten();
void testTarRootDir();
void testTarDirectoryTwice();
+ void testTarIgnoreRelativePathOutsideArchive();
void testCreateZip();
void testCreateZipError();
--- a/src/karchive.cpp
+++ b/src/karchive.cpp
@@ -841,6 +841,7 @@
bool KArchiveDirectory::copyTo(const QString &dest, bool recursiveCopy) const
{
QDir root;
+ const QString destDir(QDir(dest).absolutePath()); // get directory path without any "." or ".."
QList<const KArchiveFile *> fileList;
QMap<qint64, QString> fileToDir;
@@ -850,10 +851,20 @@
QStack<QString> dirNameStack;
dirStack.push(this); // init stack at current directory
- dirNameStack.push(dest); // ... with given path
+ dirNameStack.push(destDir); // ... with given path
do {
const KArchiveDirectory *curDir = dirStack.pop();
- const QString curDirName = dirNameStack.pop();
+
+ // extract only to specified folder if it is located within archive's extraction folder
+ // otherwise put file under root position in extraction folder
+ QString curDirName = dirNameStack.pop();
+ if (!QDir(curDirName).absolutePath().startsWith(destDir)) {
+ qWarning() << "Attempted export into folder" << curDirName
+ << "which is outside of the extraction root folder" << destDir << "."
+ << "Changing export of contained files to extraction root folder.";
+ curDirName = destDir;
+ }
+
if (!root.mkpath(curDirName)) {
return false;
}