diff --git a/distlib/scripts.py b/distlib/scripts.py index 0cf6640..62204ad 100644 --- a/distlib/scripts.py +++ b/distlib/scripts.py @@ -157,6 +157,12 @@ def _build_shebang(self, executable, post_interp): """ if os.name != 'posix': simple_shebang = True + elif getattr(sys, "cross_compiling", False): + # In a cross-compiling environment, the shebang will likely be a + # script; this *must* be invoked with the "safe" version of the + # shebang, or else using os.exec() to run the entry script will + # fail, raising "OSError 8 [Errno 8] Exec format error". + simple_shebang = False else: # Add 3 for '#!' prefix and newline suffix. shebang_length = len(executable) + len(post_interp) + 3 diff --git a/tests/test_scripts.py b/tests/test_scripts.py index 84112e7..479f583 100644 --- a/tests/test_scripts.py +++ b/tests/test_scripts.py @@ -121,6 +121,28 @@ def test_custom_shebang(self): actual = os.path.realpath(stdout.strip()) self.assertEqual(actual, expected.encode('utf-8')) + @unittest.skipIf(os.name != 'posix', 'Test only appropriate for ' + 'POSIX systems') + def test_cross_env_shebang(self): + # Construct an executable with a path that wouldn't ordinarily be a problem + self.maker.executable = '/path/to/python3' + + # Set the cross-compiling marker attribute, then clean up. + try: + sys.cross_compiling = True + filenames = self.maker.make('script1.py') + finally: + delattr(sys, "cross_compiling") + + with open(filenames[0], 'rb') as f: + first_line = f.readline() + second_line = f.readline() + third_line = f.readline() + self.assertEqual(first_line, b'#!/bin/sh\n') + self.assertEqual(second_line, b"'''exec' /path/to/python3 " + b'"$0" "$@"\n') + self.assertEqual(third_line, b"' '''\n") + def test_multiple(self): specs = ('foo.py', 'script1.py', 'script2.py', 'script3.py', 'shell.sh', 'uwsgi_part') files = self.maker.make_multiple(specs)