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;
         }
openSUSE Build Service is sponsored by