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:
28
tests/fixtures/README
vendored
Normal file
28
tests/fixtures/README
vendored
Normal 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
25
tests/fixtures/archive.ar
vendored
Normal 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
86
tests/test_util_ar.py
Normal 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()
|
Reference in New Issue
Block a user