From: Markus Koschany <apo@debian.org>
Date: Thu, 6 Feb 2025 19:25:20 +0100
Subject: CVE-2024-57966

Origin: https://github.com/KDE/ark/commit/fe518d81b338941e0bf1c5ce5e75a9ab6de4bb58

---
Patch taken from ark_20.12.2-1+deb11u1 without modification
and de-fuzzed.

Signed-off-by: Joe Slater <joe.slater@windriver.com>

---
 autotests/kerfuffle/extracttest.cpp     |  4 ++++
 plugins/libarchive/libarchiveplugin.cpp | 13 +++++++++----
 2 files changed, 13 insertions(+), 4 deletions(-)

diff a/autotests/kerfuffle/extracttest.cpp b/autotests/kerfuffle/extracttest.cpp
Index: ark-22.12.3/autotests/kerfuffle/extracttest.cpp
===================================================================
--- ark-22.12.3.orig/autotests/kerfuffle/extracttest.cpp	2025-05-16 22:24:08.455555221 +0000
+++ ark-22.12.3/autotests/kerfuffle/extracttest.cpp	2025-05-16 22:24:08.451555217 +0000
@@ -398,6 +398,10 @@
             << optionsPreservePaths
             << 6;
 
+    // Test tarball with leading /, i.e. here /tmp/testfile instead of tmp/testfile
+    archivePath = QFINDTESTDATA("data/absolutepath.tar.xz");
+    setupRow("extract all entries from a tar archive with absolute path", archivePath, QList<Archive::Entry *>(), optionsPreservePaths, 2);
+
     archivePath = QFINDTESTDATA("data/hello-1.0-x86_64.AppImage");
     QTest::newRow("extract all entries from an AppImage with path")
             << archivePath
Index: ark-22.12.3/plugins/libarchive/libarchiveplugin.cpp
===================================================================
--- ark-22.12.3.orig/plugins/libarchive/libarchiveplugin.cpp	2025-05-16 22:24:08.455555221 +0000
+++ ark-22.12.3/plugins/libarchive/libarchiveplugin.cpp	2025-05-16 22:24:08.451555217 +0000
@@ -295,6 +295,11 @@
             entryName.remove(0, 1);
         }
 
+        // If this ends up empty (e.g. from // or ./), convert to ".".
+        if (entryName.isEmpty()) {
+            entryName = QStringLiteral(".");
+        }
+
         // Should the entry be extracted?
         if (extractAll ||
             remainingFiles.contains(entryName) ||
@@ -309,10 +314,12 @@
                 continue;
             }
 
+            // Make sure libarchive uses the same path as we expect, based on transformations and renames,
+            qCDebug(ARK) << "setting path to " << entryName;
+            archive_entry_copy_pathname(entry, QFile::encodeName(entryName).constData());
             // entryFI is the fileinfo pointing to where the file will be
             // written from the archive.
             QFileInfo entryFI(entryName);
-            //qCDebug(ARK) << "setting path to " << archive_entry_pathname( entry );
 
             if (isSingleFile && fileBeingRenamed.isEmpty()) {
                 // Rename extracted file from libarchive-internal "data" name to the archive uncompressed name.
@@ -555,9 +562,7 @@
 
 int LibarchivePlugin::extractionFlags() const
 {
-    return ARCHIVE_EXTRACT_TIME
-           | ARCHIVE_EXTRACT_SECURE_NODOTDOT
-           | ARCHIVE_EXTRACT_SECURE_SYMLINKS;
+    return ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS | ARCHIVE_EXTRACT_SECURE_NODOTDOT | ARCHIVE_EXTRACT_SECURE_SYMLINKS;
 }
 
 void LibarchivePlugin::copyData(const QString& filename, struct archive *dest, bool partialprogress)
