diff options
author | 2022-11-16 01:36:09 -0500 | |
---|---|---|
committer | 2022-11-16 01:36:09 -0500 | |
commit | 8e2313dbe1a484fbf7cd518a1008387103d593ee (patch) | |
tree | 4857505197d7ea12482f13fc5755c1e18fc9b3f9 | |
parent | Add snekio.py for FileAttachment dataclass (diff) |
Implement attachment support
-rw-r--r-- | snekbox/memfs.py | 15 | ||||
-rw-r--r-- | snekbox/nsjail.py | 25 |
2 files changed, 32 insertions, 8 deletions
diff --git a/snekbox/memfs.py b/snekbox/memfs.py index 50196ce..520954b 100644 --- a/snekbox/memfs.py +++ b/snekbox/memfs.py @@ -12,7 +12,14 @@ from types import TracebackType from typing import Type from uuid import uuid4 +from snekbox.snekio import FileAttachment + +# Size of the memory filesystem MEMFS_SIZE = "2G" +# Maximum number of files attachments will be scanned for +MAX_FILES = 6 +# Maximum size of a file attachment (64 MB) +MAX_FILE_SIZE = 64 * 1024 * 1024 log = logging.getLogger(__name__) @@ -86,6 +93,14 @@ class MemoryTempDir: yield self.path.chmod(0o555) + def attachments(self) -> list[FileAttachment] | None: + """Return a list of attachments in the tempdir.""" + # First look for any file named `output` (any extension) + output = next((f for f in self.home.glob("output*") if f.is_file()), None) + if output: + return [FileAttachment.from_path(output, MAX_FILE_SIZE)] + return None + def cleanup(self) -> None: """Remove files in temp dir, releases name.""" if self.path is None: diff --git a/snekbox/nsjail.py b/snekbox/nsjail.py index c7103bd..d8b642a 100644 --- a/snekbox/nsjail.py +++ b/snekbox/nsjail.py @@ -15,6 +15,8 @@ from snekbox.memfs import MemoryTempDir __all__ = ("NsJail",) +from snekbox.snekio import FileAttachment + log = logging.getLogger(__name__) # [level][timestamp][PID]? function_signature:line_no? message @@ -131,7 +133,7 @@ class NsJail: def python3( self, code: str, *, nsjail_args: Iterable[str] = (), py_args: Iterable[str] = ("",) - ) -> CompletedProcess: + ) -> tuple[CompletedProcess, list[FileAttachment]]: """ Execute Python 3 code in an isolated environment and return the completed process. @@ -195,16 +197,19 @@ class NsJail: args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True ) except ValueError: - return CompletedProcess(args, None, "ValueError: embedded null byte", None) + return CompletedProcess(args, None, "ValueError: embedded null byte", None), [] try: output = self._consume_stdout(nsjail) except UnicodeDecodeError: - return CompletedProcess( - args, - None, - "UnicodeDecodeError: invalid Unicode in output pipe", - None, + return ( + CompletedProcess( + args, + None, + "UnicodeDecodeError: invalid Unicode in output pipe", + None, + ), + [], ) # When you send signal `N` to a subprocess to terminate it using Popen, it @@ -212,6 +217,10 @@ class NsJail: # convert negative exit codes to the `N + 128` form. returncode = -nsjail.returncode + 128 if nsjail.returncode < 0 else nsjail.returncode + # Parse attachments + attachments = temp_dir.attachments() or [] + log.info(f"Found {len(attachments)} attachments.") + log_lines = nsj_log.read().decode("utf-8").splitlines() if not log_lines and returncode == 255: # NsJail probably failed to parse arguments so log output will still be in stdout @@ -221,4 +230,4 @@ class NsJail: log.info(f"nsjail return code: {returncode}") - return CompletedProcess(args, returncode, output, None) + return CompletedProcess(args, returncode, output, None), attachments |