Skip to content
This repository was archived by the owner on Oct 2, 2026. It is now read-only.

Commit 5ecd2ea

Browse files
authored
Merge pull request #7 from lbgos/fix/binary-exec-output
Handle binary Docker command output without aborting attempts
2 parents 3b6caa3 + f74cc3e commit 5ecd2ea

2 files changed

Lines changed: 27 additions & 1 deletion

File tree

‎rangebench/env.py‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,9 @@ def load_all() -> list[Task]:
154154

155155
def _run(cmd: list[str], timeout: int = 300, check: bool = True) -> subprocess.CompletedProcess:
156156
try:
157-
proc = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
157+
proc = subprocess.run(
158+
cmd, capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=timeout
159+
)
158160
except subprocess.TimeoutExpired as exc:
159161
raise EnvError(f"{' '.join(cmd[:6])}... timed out after {timeout}s") from exc
160162
if check and proc.returncode != 0:
@@ -385,6 +387,8 @@ def attacker_available() -> bool:
385387
["docker", "exec", self.attacker, "true"],
386388
capture_output=True,
387389
text=True,
390+
encoding="utf-8",
391+
errors="replace",
388392
timeout=10,
389393
)
390394
except subprocess.TimeoutExpired as exc:
@@ -413,6 +417,8 @@ def attacker_available() -> bool:
413417
],
414418
capture_output=True,
415419
text=True,
420+
encoding="utf-8",
421+
errors="replace",
416422
timeout=timeout + 15,
417423
)
418424
stderr = (proc.stderr or "").lstrip()

‎tests/test_accounting.py‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import json
33
import tempfile
44
import subprocess
5+
import sys
56
import unittest
67
from pathlib import Path
78
from unittest.mock import patch
@@ -374,6 +375,25 @@ def test_model_stderr_that_looks_like_docker_error_is_scored(self) -> None:
374375
self.assertEqual(rc, 1)
375376
self.assertIn("pretend", out)
376377

378+
def test_binary_attacker_output_is_returned_with_replacement_characters(self) -> None:
379+
task = Task("sample", Path("/tmp"), "web", 1, "Find the flag")
380+
env = TaskEnv(task, "rb-test")
381+
actual_run = subprocess.run
382+
383+
def binary_output(_cmd: list[str], **kwargs):
384+
return actual_run(
385+
[
386+
sys.executable,
387+
"-c",
388+
"import sys; sys.stdout.buffer.write(b'out\\xff'); "
389+
"sys.stderr.buffer.write(b'err\\xfe')",
390+
],
391+
**kwargs,
392+
)
393+
394+
with patch("rangebench.env.subprocess.run", side_effect=binary_output):
395+
self.assertEqual(env.exec("cat binary-file"), (0, "out\ufffd\n[stderr]\nerr\ufffd"))
396+
377397
def test_attacker_uses_recorded_image_id(self) -> None:
378398
task = Task("sample", Path("/tmp"), "web", 1, "Find the flag")
379399
env = TaskEnv(task, "rb-test", "sha256:recorded")

0 commit comments

Comments
 (0)