Last active
February 22, 2018 15:42
-
-
Save boronine/e5fe9198374d9a9b6270470ed98e4697 to your computer and use it in GitHub Desktop.
Test maximum shebang length
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import stat | |
import tempfile | |
import subprocess | |
shebang_prefix = '#!/usr/bin/env DUMMY=x' | |
shebang_suffix = ' python\n' | |
shebang_length_min = len(shebang_prefix) + len(shebang_suffix) | |
TEST_FILE_HANDLE, TEST_FILE = tempfile.mkstemp('.py') | |
def executable(shebang_length): | |
assert shebang_length >= shebang_length_min | |
num_extra_chars = shebang_length - shebang_length_min | |
extra_chars = 'x' * num_extra_chars | |
shebang = shebang_prefix + extra_chars + shebang_suffix | |
return shebang + 'import sys; sys.exit(7)\n' | |
def shebang_works(shebang_length): | |
with open(TEST_FILE, 'w') as f: | |
f.write(executable(shebang_length)) | |
# Make executable | |
st = os.stat(TEST_FILE) | |
os.chmod(TEST_FILE, st.st_mode | stat.S_IEXEC) | |
os.close(TEST_FILE_HANDLE) | |
try: | |
subprocess.check_output([TEST_FILE]) | |
except subprocess.CalledProcessError as e: | |
if e.returncode == 7: | |
return True | |
except OSError as err: | |
if err.args == (8, 'Exec format error'): | |
# This OSError means shebang is bad | |
return False | |
else: | |
# Not sure what this one means | |
raise err | |
return False | |
def main(): | |
# shebang works when (<=) bound_lower and does not work when (>=) bound_upper | |
bound_lower = length_test = 32 | |
bound_upper = None | |
print('finding upper bound') | |
while bound_upper is None: | |
if shebang_works(length_test): | |
bound_lower = length_test | |
length_test *= 2 | |
else: | |
bound_upper = length_test | |
print('searching cutoff') | |
while bound_upper - bound_lower > 1: | |
length_test = bound_lower + (bound_upper - bound_lower) // 2 | |
if shebang_works(length_test): | |
bound_lower = length_test | |
else: | |
bound_upper = length_test | |
print('maximum shebang length (including newline)') | |
print(bound_lower) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment