aboutsummaryrefslogtreecommitdiffstats
path: root/src/scripts
diff options
context:
space:
mode:
authorSimon Warta <[email protected]>2017-08-04 13:16:25 +0200
committerSimon Warta <[email protected]>2017-08-04 13:16:25 +0200
commit53d1b0faf2d264e03933b2f1e578ff19c6209aa3 (patch)
tree6dd0181d0483a30a0e53ca672d4c7935727c8419 /src/scripts
parent898e3a032c23623cd8296c30269f2ed148b7234e (diff)
Handle and test error cases in prepend_destdir()
- only / file systems supported - only absolute prefixes are supported - result must not escape DESTDIR
Diffstat (limited to 'src/scripts')
-rwxr-xr-xsrc/scripts/install.py48
-rwxr-xr-xsrc/scripts/python_unittests_unix.py46
2 files changed, 50 insertions, 44 deletions
diff --git a/src/scripts/install.py b/src/scripts/install.py
index 1875bd62d..9f7363a48 100755
--- a/src/scripts/install.py
+++ b/src/scripts/install.py
@@ -64,6 +64,14 @@ def parse_command_line(args):
return (options, args)
+class PrependDestdirError(Exception):
+ pass
+
+
+def is_subdir(path, subpath):
+ return os.path.relpath(path, start=subpath).startswith("..")
+
+
def prepend_destdir(path):
"""
Needed because os.path.join() discards the first path if the
@@ -73,40 +81,22 @@ def prepend_destdir(path):
"""
destdir = os.environ.get('DESTDIR', "")
- if destdir != "":
- #DESTDIR is non-empty, but we cannot join all prefix paths.
-
- #These will be rejected via an exception:
- # C:/foo
- # C:foo
- # \\foo (Python >3.1 only)
- # \\foo\bar (Python >3.1 only)
- # ../somewhere/else
-
- #These will be normalized to a relative path and joined with DESTDIR:
- # /absolute/dir
- # relative/dir
- # /dir/with/../inside
- # ./relative/to/me
- # ~/botan-install-test
-
- # ".." makes no sense, as it would certainly escape the DESTDIR prefix
- if path.startswith(".."):
- raise Exception('With DESTDIR set, a prefix starting in ".." would escape the destdir. Aborting.')
-
- # Will only trigger on Windows, see the splitdrive() doc for details
- drive, _ = os.path.splitdrive(path)
- if drive != "":
- raise Exception('DESTDIR set, but drive or UNC detected in prefix path. Aborting.')
-
- # resolved ~, ~user
- path = os.path.expanduser(path)
- # native slashes, ".." inside (not in front of) pathes normalized
+ if destdir:
+ # DESTDIR is non-empty, but we only join absolute paths on UNIX-like file systems
+ if os.path.sep != "/":
+ raise PrependDestdirError("Only UNIX-like file systems using forward slash " \
+ "separator supported when DESTDIR is set.")
+ if not os.path.isabs(path):
+ raise PrependDestdirError("--prefix must be an absolute path when DESTDIR is set.")
+
path = os.path.normpath(path)
# Remove / or \ prefixes if existent to accomodate for os.path.join()
path = path.lstrip(os.path.sep)
path = os.path.join(destdir, path)
+ if not is_subdir(destdir, path):
+ raise PrependDestdirError("path escapes DESTDIR (path='%s', destdir='%s')" % (path, destdir))
+
return path
diff --git a/src/scripts/python_unittests_unix.py b/src/scripts/python_unittests_unix.py
index a8015d081..fe9f06a62 100755
--- a/src/scripts/python_unittests_unix.py
+++ b/src/scripts/python_unittests_unix.py
@@ -17,33 +17,49 @@ import unittest
sys.path.append("../..") # Botan repo root
from install import prepend_destdir # pylint: disable=wrong-import-position
+from install import PrependDestdirError # pylint: disable=wrong-import-position
class PrependDestdir(unittest.TestCase):
- def test_base(self):
+ def test_absolute_destdir(self):
os.environ["DESTDIR"] = "/"
self.assertEqual(prepend_destdir("/home/me"), "/home/me")
- self.assertEqual(prepend_destdir("relative_path"), "/relative_path")
- self.assertEqual(prepend_destdir("./relative_path"), "/relative_path")
- self.assertEqual(prepend_destdir("relative/sub"), "/relative/sub")
-
self.assertEqual(prepend_destdir("/home/me/"), "/home/me")
- self.assertEqual(prepend_destdir("relative_path/"), "/relative_path")
-
self.assertEqual(prepend_destdir("/home/me/../me2"), "/home/me2")
- self.assertEqual(prepend_destdir("relative/sub/../sub2"), "/relative/sub2")
os.environ["DESTDIR"] = "/opt"
self.assertEqual(prepend_destdir("/home/me"), "/opt/home/me")
- self.assertEqual(prepend_destdir("relative_path"), "/opt/relative_path")
- self.assertEqual(prepend_destdir("./relative_path"), "/opt/relative_path")
- self.assertEqual(prepend_destdir("relative/sub"), "/opt/relative/sub")
-
self.assertEqual(prepend_destdir("/home/me/"), "/opt/home/me")
- self.assertEqual(prepend_destdir("relative_path/"), "/opt/relative_path")
-
self.assertEqual(prepend_destdir("/home/me/../me2"), "/opt/home/me2")
- self.assertEqual(prepend_destdir("relative/sub/../sub2"), "/opt/relative/sub2")
+
+ def test_relative_destdir(self):
+ os.environ["DESTDIR"] = "."
+ self.assertEqual(prepend_destdir("/home/me"), "./home/me")
+ self.assertEqual(prepend_destdir("/home/me/"), "./home/me")
+ self.assertEqual(prepend_destdir("/home/me/../me2"), "./home/me2")
+
+ os.environ["DESTDIR"] = "bar"
+ self.assertEqual(prepend_destdir("/home/me"), "bar/home/me")
+ self.assertEqual(prepend_destdir("/home/me/"), "bar/home/me")
+ self.assertEqual(prepend_destdir("/home/me/../me2"), "bar/home/me2")
+
+ def test_relative(self):
+ # No destdir set
+ os.environ["DESTDIR"] = ""
+ self.assertEqual(prepend_destdir("foo"), "foo")
+ self.assertEqual(prepend_destdir("../foo"), "../foo")
+
+ # Destdir set
+ os.environ["DESTDIR"] = "/opt"
+ with self.assertRaises(PrependDestdirError):
+ prepend_destdir("foo")
+ with self.assertRaises(PrependDestdirError):
+ prepend_destdir("../foo")
+
+ def test_escaping(self):
+ os.environ["DESTDIR"] = "/opt"
+ with self.assertRaises(PrependDestdirError):
+ prepend_destdir("/foo/../..")
if __name__ == '__main__':