1
0
mirror of https://github.com/openSUSE/osc.git synced 2025-09-07 13:48:43 +02:00

Forbid extracting files with absolute path from 'ar' archives (boo#1122683)

Also fix and modernize the code, add tests.
This commit is contained in:
2024-05-29 16:12:46 +02:00
parent a3ed68508b
commit d61b781976
4 changed files with 176 additions and 25 deletions

28
tests/fixtures/README vendored Normal file
View File

@@ -0,0 +1,28 @@
Generate data for creating test archives
----------------------------------------
echo 'foobar' > /tmp/foo
# root perms required for the next command
echo 'numbers' > /123
echo 'qwerty' > very-long-long-long-long-name
echo 'asdfgh' > very-long-long-long-long-name2
echo 'newline' > 'very-long-name
-with-newline'
echo 'newline' > 'a
b'
mkdir 'dir'
echo 'file-in-a-dir' > dir/file
Create archive.ar
-----------------
ar qP archive.ar /tmp/foo /123 very-long-long-long-long-name very-long-long-long-long-name2 'very-long-name
-with-newline' 'a
b' dir/file

25
tests/fixtures/archive.ar vendored Normal file
View File

@@ -0,0 +1,25 @@
!<arch>
// 94 `
very-long-long-long-long-name/
very-long-long-long-long-name2/
very-long-name
-with-newline/
/tmp/foo/ 1716888536 1000 1000 100644 7 `
foobar
/123/ 1716883776 0 0 100644 8 `
numbers
/0 1716882802 1000 1000 100644 7 `
qwerty
/31 1716882988 1000 1000 100644 7 `
asdfgh
/63 1716884767 1000 1000 100644 8 `
newline
a
b/ 1716884876 1000 1000 100644 8 `
newline
dir/file/ 1716992150 1000 1000 100644 14 `
file-in-a-dir

86
tests/test_util_ar.py Normal file
View File

@@ -0,0 +1,86 @@
import os
import shutil
import tempfile
import unittest
from osc.util.ar import Ar
from osc.util.ar import ArError
FIXTURES_DIR = os.path.join(os.path.dirname(__file__), "fixtures")
class TestAr(unittest.TestCase):
def setUp(self):
self.tmpdir = tempfile.mkdtemp(prefix="osc_test_")
try:
self.old_cwd = os.getcwd()
except FileNotFoundError:
self.old_cwd = os.path.expanduser("~")
os.chdir(self.tmpdir)
self.archive = os.path.join(FIXTURES_DIR, "archive.ar")
self.ar = Ar(self.archive)
self.ar.read()
def tearDown(self):
os.chdir(self.old_cwd)
shutil.rmtree(self.tmpdir)
def test_file_list(self):
actual = [i.name for i in self.ar]
expected = [
# absolute path
b"/tmp/foo",
# this is a filename, not a long filename reference
b"/123",
b"very-long-long-long-long-name",
b"very-long-long-long-long-name2",
# long file name with a newline
b"very-long-name\n-with-newline",
# short file name with a newline
b"a\nb",
b"dir/file",
]
self.assertEqual(actual, expected)
def test_get_file(self):
f = self.ar.get_file(b"/tmp/foo")
self.assertIsNotNone(f)
f = self.ar.get_file("/tmp/foo")
self.assertIsNotNone(f)
f = self.ar.get_file("does-not-exist")
self.assertIsNone(f)
def test_saveTo(self):
f = self.ar.get_file("a\nb")
path = f.saveTo(self.tmpdir)
# check that we've got the expected path
self.assertEqual(path, os.path.join(self.tmpdir, "a\nb"))
# ... and that the contents also match
with open(path, "r", encoding="utf-8") as f:
self.assertEqual(f.read(), "newline\n")
def test_saveTo_subdir(self):
f = self.ar.get_file("dir/file")
path = f.saveTo(self.tmpdir)
# check that we've got the expected path
self.assertEqual(path, os.path.join(self.tmpdir, "dir/file"))
# ... and that the contents also match
with open(path, "r", encoding="utf-8") as f:
self.assertEqual(f.read(), "file-in-a-dir\n")
def test_saveTo_abspath(self):
f = self.ar.get_file("/tmp/foo")
assert f is not None
# this is supposed to throw an error, extracting files with absolute paths might overwrite system files
self.assertRaises(ArError, f.saveTo, self.tmpdir)
if __name__ == "__main__":
unittest.main()