1
0
mirror of https://github.com/openSUSE/osc.git synced 2025-09-07 21:58:41 +02:00

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

Also fix and modernize the code, add tests.
This commit is contained in:
2024-05-30 11:12:09 +02:00
parent d61b781976
commit 5cbd110a84
4 changed files with 97 additions and 4 deletions

View File

@@ -26,3 +26,10 @@ 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
Create archive.cpio
-------------------
printf "/tmp/foo\0/123\0very-long-long-long-long-name\0very-long-long-long-long-name2\0very-long-name
-with-newline\0a\nb\0dir/file\0" | cpio -ocv0 --owner=root:root > archive.cpio

BIN
tests/fixtures/archive.cpio vendored Normal file

Binary file not shown.

71
tests/test_util_cpio.py Normal file
View File

@@ -0,0 +1,71 @@
import os
import shutil
import tempfile
import unittest
from osc.util.cpio import CpioRead
from osc.util.cpio import CpioError
FIXTURES_DIR = os.path.join(os.path.dirname(__file__), "fixtures")
class TestCpio(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.cpio")
self.cpio = CpioRead(self.archive)
self.cpio.read()
def tearDown(self):
os.chdir(self.old_cwd)
shutil.rmtree(self.tmpdir)
def test_file_list(self):
actual = [i.filename for i in self.cpio]
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_copyin_file(self):
path = self.cpio.copyin_file("a\nb", dest=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_copyin_file_abspath(self):
self.assertRaises(CpioError, self.cpio.copyin_file, "/tmp/foo")
def test_copyin_file_subdir(self):
path = self.cpio.copyin_file("dir/file", dest=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")
if __name__ == "__main__":
unittest.main()