From 5e19ba6052dca04cd1759bd3da53ef164dcc19cc Mon Sep 17 00:00:00 2001 From: Thomas Woerner Date: Wed, 6 Dec 2023 19:00:28 +0100 Subject: [PATCH] Fix link target generation for collection test (#252) The link_target was generated only using the extract_dir and the linkname, but without the directory path that contains the link. Therefore the link_target could be outside of extract_dir. No-Issue Signed-off-by: Thomas Woerner --- galaxy_importer/collection.py | 4 ++- tests/unit/test_collection_archive_extract.py | 36 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/galaxy_importer/collection.py b/galaxy_importer/collection.py index 4605a2a0..8bda1316 100644 --- a/galaxy_importer/collection.py +++ b/galaxy_importer/collection.py @@ -165,7 +165,9 @@ def _extract_archive(fileobj, extract_dir): raise exc.ImporterError("Invalid file paths detected.") if item.linkname: # Ensure the link target is within the extraction root - link_target = os.path.normpath(os.path.join(extract_dir, item.linkname)) + link_target = os.path.normpath( + os.path.join(extract_dir, os.path.dirname(item.name), item.linkname) + ) if not link_target.startswith(os.path.abspath(extract_dir)): raise exc.ImporterError("Invalid link target detected.") tf.extractall(extract_dir) diff --git a/tests/unit/test_collection_archive_extract.py b/tests/unit/test_collection_archive_extract.py index 47e997d3..ef645b4b 100644 --- a/tests/unit/test_collection_archive_extract.py +++ b/tests/unit/test_collection_archive_extract.py @@ -119,3 +119,39 @@ def test_invalid_link_destination(self): # Clean up the temporary extraction directory os.rmdir(extract_dir) + + def test_valid_relative_symlink_in_subdir(self): + # Create a valid archive with a relative symlink in a subdir + # and the target in the top dir + archive_data = b"testfile content" + archive_file = BytesIO() + with tarfile.open(fileobj=archive_file, mode="w") as tf: + tarinfo = tarfile.TarInfo(".") + tarinfo.type = tarfile.DIRTYPE + tarinfo.mode = 493 + tf.addfile(tarinfo, BytesIO(archive_data)) + tarinfo.name = "testdir1" + tf.addfile(tarinfo, BytesIO(archive_data)) + tarinfo.name = "testdir2" + tf.addfile(tarinfo, BytesIO(archive_data)) + tarinfo.name = "testdir2/link" + tarinfo.type = tarfile.SYMTYPE + tarinfo.mode = 511 + tarinfo.linkname = "../testdir1" + tf.addfile(tarinfo, BytesIO(archive_data)) + archive_file.seek(0) + + # Create a temporary extraction directory + extract_dir = tempfile.mkdtemp(prefix="collection-archive-extract-test-") + os.makedirs(extract_dir, exist_ok=True) + + try: + _extract_archive(archive_file, extract_dir) + finally: + pass + + extracted_file_path = os.path.join(extract_dir, "testdir2/link") + self.assertTrue(os.path.islink(extracted_file_path)) + + # Clean up the temporary extraction directory + shutil.rmtree(extract_dir)