Skip to content

Commit

Permalink
Handle EvalError in a centralised location
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkKoz committed Sep 16, 2023
1 parent e1af1ec commit 09dd215
Showing 1 changed file with 27 additions and 32 deletions.
59 changes: 27 additions & 32 deletions snekbox/nsjail.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,14 +149,18 @@ def _consume_stdout(self, nsjail: subprocess.Popen) -> str:
with nsjail:
# We'll consume STDOUT as long as the NsJail subprocess is running.
while nsjail.poll() is None:
chars = nsjail.stdout.read(self.read_chunk_size)
try:
chars = nsjail.stdout.read(self.read_chunk_size)
except UnicodeDecodeError as e:
raise EvalError("UnicodeDecodeError: invalid Unicode in output pipe") from e

output_size += sys.getsizeof(chars)
output.append(chars)

if output_size > self.max_output_size:
# Terminate the NsJail subprocess with SIGTERM.
# This in turn reaps and kills children with SIGKILL.
log.info("Output exceeded the output limit, sending SIGTERM to NsJail.")
log.info("Output exceeded the output limit. Sending SIGTERM to NsJail.")
nsjail.terminate()
break

Expand Down Expand Up @@ -264,46 +268,37 @@ def python3(
output=self.memfs_output,
) as fs:
args = self._build_args(py_args, nsjail_args, nsj_log.name, str(fs.home))

try:
files_written = self._write_files(fs.home, files)
except EvalError as e:
return EvalResult(args, None, str(e))

msg = "Executing code..."
if DEBUG:
msg = f"{msg[:-3]} with the arguments {args}."
log.info(msg)
msg = "Executing code..."
if DEBUG:
msg = f"{msg[:-3]} with the arguments {args}."
log.info(msg)

try:
nsjail = subprocess.Popen(
args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True
)
except ValueError:
return EvalResult(args, None, "ValueError: embedded null byte")
try:
nsjail = subprocess.Popen(
args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True
)
except ValueError:
return EvalResult(args, None, "ValueError: embedded null byte")

try:
output = self._consume_stdout(nsjail)
except UnicodeDecodeError:
return EvalResult(args, None, "UnicodeDecodeError: invalid Unicode in output pipe")

# When you send signal `N` to a subprocess to terminate it using Popen, it
# will return `-N` as its exit code. As we normally get `N + 128` back, we
# convert negative exit codes to the `N + 128` form.
returncode = -nsjail.returncode + 128 if nsjail.returncode < 0 else nsjail.returncode

try:
attachments = self._parse_attachments(fs, files_written)
log_lines = nsj_log.read().decode("utf-8").splitlines()
except EvalError as e:
return EvalResult(args, None, str(e))

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
log_lines = output.splitlines()
# When you send signal `N` to a subprocess to terminate it using Popen, it
# will return `-N` as its exit code. As we normally get `N + 128` back, we
# convert negative exit codes to the `N + 128` form.
return_code = -nsjail.returncode + 128 if nsjail.returncode < 0 else nsjail.returncode

self._parse_log(log_lines)
if not log_lines and return_code == 255:
# NsJail probably failed to parse arguments so log output will still be in stdout
log_lines = output.splitlines()

log.info(f"nsjail return code: {returncode}")
self._parse_log(log_lines)
log.info(f"NsJail return code: {return_code}")

return EvalResult(args, returncode, output, files=attachments)
return EvalResult(args, return_code, output, files=attachments)

0 comments on commit 09dd215

Please sign in to comment.