aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.flake81
-rw-r--r--Pipfile1
-rw-r--r--Pipfile.lock94
-rw-r--r--snekbox/__init__.py4
-rw-r--r--snekbox/nsjail.py66
-rw-r--r--snekbox/site/snekapp.py10
-rw-r--r--tests/test_snekbox.py46
7 files changed, 119 insertions, 103 deletions
diff --git a/.flake8 b/.flake8
index f8eec98..347bdb0 100644
--- a/.flake8
+++ b/.flake8
@@ -16,3 +16,4 @@ exclude=
venv,.venv,
tests
import-order-style=pycharm
+inline-quotes = "
diff --git a/Pipfile b/Pipfile
index 788e900..69bb0df 100644
--- a/Pipfile
+++ b/Pipfile
@@ -20,6 +20,7 @@ flake8-tidy-imports = "*"
flake8-todo = "*"
flake8-string-format = "*"
flake8-formatter-junit-xml = "*"
+flake8-quotes = "*"
[requires]
python_version = "3.7"
diff --git a/Pipfile.lock b/Pipfile.lock
index 466a42b..b73b997 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "814185e2e1b964ab58af9a9df416ace7b5b416475d828ec9b31a9dfecb5693e1"
+ "sha256": "c1f4c3df791d8c4758f72cb8fb148a34d5c1ca02298b0d660844899f15f6ba85"
},
"pipfile-spec": 6,
"requires": {
@@ -25,11 +25,11 @@
},
"flask": {
"hashes": [
- "sha256:2271c0070dbcb5275fad4a82e29f23ab92682dc45f9dfbc22c02ba9b9322ce48",
- "sha256:a080b744b7e345ccfcbc77954861cb05b3c63786e93f2b3875e0913d44b43f05"
+ "sha256:ad7c6d841e64296b962296c2c2dabc6543752985727af86a975072dea984b6f3",
+ "sha256:e7d32475d1de5facaa55e3958bc4ec66d3762076b074296aa50ef8fdc5b9df61"
],
"index": "pypi",
- "version": "==1.0.2"
+ "version": "==1.0.3"
},
"gunicorn": {
"hashes": [
@@ -48,10 +48,10 @@
},
"jinja2": {
"hashes": [
- "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd",
- "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4"
+ "sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013",
+ "sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b"
],
- "version": "==2.10"
+ "version": "==2.10.1"
},
"markupsafe": {
"hashes": [
@@ -88,19 +88,19 @@
},
"werkzeug": {
"hashes": [
- "sha256:96da23fa8ccecbc3ae832a83df5c722c11547d021637faacb0bec4dd2f4666c8",
- "sha256:ca5c2dcd367d6c0df87185b9082929d255358f5391923269335782b213d52655"
+ "sha256:865856ebb55c4dcd0630cdd8f3331a1847a819dda7e8c750d3db6f2aa6c0209c",
+ "sha256:a0b915f0815982fb2a09161cb8f31708052d0951c3ba433ccc5e1aa276507ca6"
],
- "version": "==0.15.1"
+ "version": "==0.15.4"
}
},
"develop": {
"aspy.yaml": {
"hashes": [
- "sha256:ae249074803e8b957c83fdd82a99160d0d6d26dff9ba81ba608b42eebd7d8cd3",
- "sha256:c7390d79f58eb9157406966201abf26da0d56c07e0ff0deadc39c8f4dbc13482"
+ "sha256:463372c043f70160a9ec950c3f1e4c3a82db5fca01d334b6bc89c7164d744bdc",
+ "sha256:e7c742382eff2caed61f87a39d13f99109088e5e93f04d76eb8d4b28aa143f45"
],
- "version": "==1.2.0"
+ "version": "==1.3.0"
},
"atomicwrites": {
"hashes": [
@@ -118,10 +118,10 @@
},
"cfgv": {
"hashes": [
- "sha256:39f8475d8eca48639f900daffa3f8bd2f60a31d989df41a9f81c5ad1779a66eb",
- "sha256:a6a4366d32799a6bfb6f577ebe113b27ba8d1bae43cb57133b1472c1c3dae227"
+ "sha256:32edbe09de6f4521224b87822103a8c16a614d31a894735f7a5b3bcf0eb3c37e",
+ "sha256:3bd31385cd2bebddbba8012200aaf15aa208539f1b33973759b4d02fc2148da5"
],
- "version": "==1.5.0"
+ "version": "==2.0.0"
},
"coverage": {
"hashes": [
@@ -213,6 +213,13 @@
],
"version": "==1.0.2"
},
+ "flake8-quotes": {
+ "hashes": [
+ "sha256:10c9af6b472d4302a8e721c5260856c3f985c5c082b04841aefd2f808ac02038"
+ ],
+ "index": "pypi",
+ "version": "==2.0.1"
+ },
"flake8-string-format": {
"hashes": [
"sha256:68ea72a1a5b75e7018cae44d14f32473c798cf73d75cbaed86c6a9a907b770b2",
@@ -238,17 +245,17 @@
},
"identify": {
"hashes": [
- "sha256:244e7864ef59f0c7c50c6db73f58564151d91345cd9b76ed793458953578cadd",
- "sha256:8ff062f90ad4b09cfe79b5dfb7a12e40f19d2e68a5c9598a49be45f16aba7171"
+ "sha256:432c548d6138cb57a3d8f62f079a025a29b8ae34a50dd3b496bbf661818f2bc0",
+ "sha256:d4401d60bf1938aa3074a352a5cc9044107edf11a6fedd3a1db172c141619b81"
],
- "version": "==1.4.1"
+ "version": "==1.4.3"
},
"importlib-metadata": {
"hashes": [
- "sha256:a17ce1a8c7bff1e8674cb12c992375d8d0800c9190177ecf0ad93e0097224095",
- "sha256:b50191ead8c70adfa12495fba19ce6d75f2e0275c14c5a7beb653d6799b512bd"
+ "sha256:a9f185022cfa69e9ca5f7eabfd5a58b689894cb78a11e3c8c89398a8ccbb8e7f",
+ "sha256:df1403cd3aebeb2b1dcd3515ca062eecb5bd3ea7611f18cba81130c68707e879"
],
- "version": "==0.8"
+ "version": "==0.17"
},
"junit-xml": {
"hashes": [
@@ -279,18 +286,18 @@
},
"pluggy": {
"hashes": [
- "sha256:19ecf9ce9db2fce065a7a0586e07cfb4ac8614fe96edf628a264b1c70116cf8f",
- "sha256:84d306a647cc805219916e62aab89caa97a33a1dd8c342e87a37f91073cd4746"
+ "sha256:0825a152ac059776623854c1543d65a4ad408eb3d33ee114dff91e57ec6ae6fc",
+ "sha256:b9817417e95936bf75d85d3f8767f7df6cdde751fc40aed3bb3074cbcb77757c"
],
- "version": "==0.9.0"
+ "version": "==0.12.0"
},
"pre-commit": {
"hashes": [
- "sha256:d3d69c63ae7b7584c4b51446b0b583d454548f9df92575b2fe93a68ec800c4d3",
- "sha256:fc512f129b9526e35e80d656a16a31c198f584c4fce3a5c739045b5140584917"
+ "sha256:6ca409d1f22d444af427fb023a33ca8b69625d508a50e1b7eaabd59247c93043",
+ "sha256:94dd519597f5bff06a4b0df194a79c524b78f4b1534c1ce63241a9d4fb23b926"
],
"index": "pypi",
- "version": "==1.14.4"
+ "version": "==1.16.1"
},
"py": {
"hashes": [
@@ -323,19 +330,19 @@
},
"pytest": {
"hashes": [
- "sha256:592eaa2c33fae68c7d75aacf042efc9f77b27c08a6224a4f59beab8d9a420523",
- "sha256:ad3ad5c450284819ecde191a654c09b0ec72257a2c711b9633d677c71c9850c4"
+ "sha256:1a8aa4fa958f8f451ac5441f3ac130d9fc86ea38780dd2715e6d5c5882700b24",
+ "sha256:b8bf138592384bd4e87338cb0f256bf5f615398a649d4bd83915f0e4047a5ca6"
],
"index": "pypi",
- "version": "==4.3.1"
+ "version": "==4.5.0"
},
"pytest-cov": {
"hashes": [
- "sha256:0ab664b25c6aa9716cbf203b17ddb301932383046082c081b9848a0edf5add33",
- "sha256:230ef817450ab0699c6cc3c9c8f7a829c34674456f2ed8df1fe1d39780f7c87f"
+ "sha256:2b097cde81a302e1047331b48cadacf23577e431b61e9c6f49a1170bbe3d3da6",
+ "sha256:e00ea4fdde970725482f1f35630d12f074e121a23801aabf2ae154ec6bdd343a"
],
"index": "pypi",
- "version": "==2.6.1"
+ "version": "==2.7.1"
},
"pytest-dependency": {
"hashes": [
@@ -383,17 +390,24 @@
},
"virtualenv": {
"hashes": [
- "sha256:6aebaf4dd2568a0094225ebbca987859e369e3e5c22dc7d52e5406d504890417",
- "sha256:984d7e607b0a5d1329425dd8845bd971b957424b5ba664729fab51ab8c11bc39"
+ "sha256:99acaf1e35c7ccf9763db9ba2accbca2f4254d61d1912c5ee364f9cc4a8942a0",
+ "sha256:fe51cdbf04e5d8152af06c075404745a7419de27495a83f0d72518ad50be3ce8"
+ ],
+ "version": "==16.6.0"
+ },
+ "wcwidth": {
+ "hashes": [
+ "sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e",
+ "sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c"
],
- "version": "==16.4.3"
+ "version": "==0.1.7"
},
"zipp": {
"hashes": [
- "sha256:55ca87266c38af6658b84db8cfb7343cdb0bf275f93c7afaea0d8e7a209c7478",
- "sha256:682b3e1c62b7026afe24eadf6be579fb45fec54c07ea218bded8092af07a68c4"
+ "sha256:8c1019c6aad13642199fbe458275ad6a84907634cc9f0989877ccc4a2840139d",
+ "sha256:ca943a7e809cc12257001ccfb99e3563da9af99d52f261725e96dfe0f9275bc3"
],
- "version": "==0.3.3"
+ "version": "==0.5.1"
}
}
}
diff --git a/snekbox/__init__.py b/snekbox/__init__.py
index fc6070e..f14fc89 100644
--- a/snekbox/__init__.py
+++ b/snekbox/__init__.py
@@ -1,8 +1,8 @@
import logging
import sys
-logformat = logging.Formatter(fmt='[%(asctime)s] [%(process)s] [%(levelname)s] %(message)s',
- datefmt='%Y-%m-%d %H:%M:%S %z')
+logformat = logging.Formatter(fmt="[%(asctime)s] [%(process)s] [%(levelname)s] %(message)s",
+ datefmt="%Y-%m-%d %H:%M:%S %z")
log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)
console = logging.StreamHandler(sys.stdout)
diff --git a/snekbox/nsjail.py b/snekbox/nsjail.py
index 5c7d0f0..c807b9e 100644
--- a/snekbox/nsjail.py
+++ b/snekbox/nsjail.py
@@ -7,25 +7,25 @@ class NsJail:
"""Core Snekbox functionality, providing safe execution of Python code."""
def __init__(self,
- nsjail_binary='nsjail',
- python_binary=os.path.dirname(sys.executable) + os.sep + 'python3.7'):
+ nsjail_binary="nsjail",
+ python_binary=os.path.dirname(sys.executable) + os.sep + "python3.7"):
self.nsjail_binary = nsjail_binary
self.python_binary = python_binary
self._nsjail_workaround()
env = {
- 'PATH': (
- '/snekbox/.venv/bin:/usr/local/bin:/usr/local/'
- 'sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
+ "PATH": (
+ "/snekbox/.venv/bin:/usr/local/bin:/usr/local/"
+ "sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
),
- 'LANG': 'en_US.UTF-8',
- 'PYTHON_VERSION': '3.7.3',
- 'PYTHON_PIP_VERSION': '19.0.3',
- 'PYTHONDONTWRITEBYTECODE': '1',
+ "LANG": "en_US.UTF-8",
+ "PYTHON_VERSION": "3.7.3",
+ "PYTHON_PIP_VERSION": "19.0.3",
+ "PYTHONDONTWRITEBYTECODE": "1",
}
def _nsjail_workaround(self):
- dirs = ['/sys/fs/cgroup/pids/NSJAIL', '/sys/fs/cgroup/memory/NSJAIL']
+ dirs = ["/sys/fs/cgroup/pids/NSJAIL", "/sys/fs/cgroup/memory/NSJAIL"]
for d in dirs:
if not os.path.exists(d):
os.makedirs(d)
@@ -41,20 +41,20 @@ class NsJail:
Returns the output of executing the command (stdout) if
successful, or a error message if the execution failed.
"""
- args = [self.nsjail_binary, '-Mo',
- '--rlimit_as', '700',
- '--chroot', '/',
- '-E', 'LANG=en_US.UTF-8',
- '-R/usr', '-R/lib', '-R/lib64',
- '--user', 'nobody',
- '--group', 'nogroup',
- '--time_limit', '2',
- '--disable_proc',
- '--iface_no_lo',
- '--cgroup_pids_max=1',
- '--cgroup_mem_max=52428800',
- '--quiet', '--',
- self.python_binary, '-ISq', '-c', cmd]
+ args = [self.nsjail_binary, "-Mo",
+ "--rlimit_as", "700",
+ "--chroot", "/",
+ "-E", "LANG=en_US.UTF-8",
+ "-R/usr", "-R/lib", "-R/lib64",
+ "--user", "nobody",
+ "--group", "nogroup",
+ "--time_limit", "2",
+ "--disable_proc",
+ "--iface_no_lo",
+ "--cgroup_pids_max=1",
+ "--cgroup_mem_max=52428800",
+ "--quiet", "--",
+ self.python_binary, "-ISq", "-c", cmd]
try:
proc = subprocess.Popen(args,
stdin=subprocess.PIPE,
@@ -63,7 +63,7 @@ class NsJail:
env=self.env,
universal_newlines=True)
except ValueError:
- return 'ValueError: embedded null byte'
+ return "ValueError: embedded null byte"
stdout, stderr = proc.communicate()
if proc.returncode == 0:
@@ -72,23 +72,23 @@ class NsJail:
elif proc.returncode == 1:
try:
filtered = []
- for line in stderr.split('\n'):
- if not line.startswith('['):
+ for line in stderr.split("\n"):
+ if not line.startswith("["):
filtered.append(line)
- output = '\n'.join(filtered)
+ output = "\n".join(filtered)
except IndexError:
- output = ''
+ output = ""
elif proc.returncode == 109:
- return 'timed out or memory limit exceeded'
+ return "timed out or memory limit exceeded"
elif proc.returncode == 255:
- return 'permission denied (root required)'
+ return "permission denied (root required)"
elif proc.returncode:
- return f'unknown error, code: {proc.returncode}'
+ return f"unknown error, code: {proc.returncode}"
else:
- return 'unknown error, no error code'
+ return "unknown error, no error code"
return output
diff --git a/snekbox/site/snekapp.py b/snekbox/site/snekapp.py
index ef96148..3954238 100644
--- a/snekbox/site/snekapp.py
+++ b/snekbox/site/snekapp.py
@@ -12,22 +12,22 @@ app.use_reloader = False
log = app.logger
def index():
"""Return a page with a form for inputting code to be executed."""
- return render_template('index.html')
+ return render_template("index.html")
[email protected]('/result', methods=["POST", "GET"])
[email protected]("/result", methods=["POST", "GET"])
def result():
"""Execute code and return a page displaying the results."""
if request.method == "POST":
code = request.form["Code"]
output = nsjail.python3(code)
- return render_template('result.html', code=code, result=output)
+ return render_template("result.html", code=code, result=output)
[email protected]('/input', methods=["POST"])
[email protected]("/input", methods=["POST"])
def code_input():
"""Execute code and return the results."""
body = request.get_json()
diff --git a/tests/test_snekbox.py b/tests/test_snekbox.py
index c08178f..46319d6 100644
--- a/tests/test_snekbox.py
+++ b/tests/test_snekbox.py
@@ -7,44 +7,44 @@ nsjail = NsJail()
class SnekTests(unittest.TestCase):
def test_nsjail(self):
- result = nsjail.python3('print("test")')
- self.assertEquals(result.strip(), 'test')
+ result = nsjail.python3("print('test')")
+ self.assertEquals(result.strip(), "test")
# def test_memory_error(self):
- # code = ('x = "*"\n'
- # 'while True:\n'
- # ' x = x * 99\n')
+ # code = ("x = "*"\n"
+ # "while True:\n"
+ # " x = x * 99\n")
# result = nsjail.python3(code)
- # self.assertEquals(result.strip(), 'timed out or memory limit exceeded')
+ # self.assertEquals(result.strip(), "timed out or memory limit exceeded")
def test_timeout(self):
code = (
- 'x = "*"\n'
- 'while True:\n'
- ' try:\n'
- ' x = x * 99\n'
- ' except:\n'
- ' continue\n'
+ "x = '*'\n"
+ "while True:\n"
+ " try:\n"
+ " x = x * 99\n"
+ " except:\n"
+ " continue\n"
)
result = nsjail.python3(code)
- self.assertEquals(result.strip(), 'timed out or memory limit exceeded')
+ self.assertEquals(result.strip(), "timed out or memory limit exceeded")
def test_kill(self):
- code = ('import subprocess\n'
- 'print(subprocess.check_output("kill -9 6", shell=True).decode())')
+ code = ("import subprocess\n"
+ "print(subprocess.check_output('kill -9 6', shell=True).decode())")
result = nsjail.python3(code)
- if 'ModuleNotFoundError' in result.strip():
- self.assertIn('ModuleNotFoundError', result.strip())
+ if "ModuleNotFoundError" in result.strip():
+ self.assertIn("ModuleNotFoundError", result.strip())
else:
- self.assertIn('(PIDs left: 0)', result.strip())
+ self.assertIn("(PIDs left: 0)", result.strip())
def test_forkbomb(self):
- code = ('import os\n'
- 'while 1:\n'
- ' os.fork()')
+ code = ("import os\n"
+ "while 1:\n"
+ " os.fork()")
result = nsjail.python3(code)
- self.assertIn('Resource temporarily unavailable', result.strip())
+ self.assertIn("Resource temporarily unavailable", result.strip())
def test_juan_golf(self): # in honour of Juan
code = ("func = lambda: None\n"
@@ -53,4 +53,4 @@ class SnekTests(unittest.TestCase):
"exec(bytecode)")
result = nsjail.python3(code)
- self.assertEquals('unknown error, code: 111', result.strip())
+ self.assertEquals("unknown error, code: 111", result.strip())