From 97c33b5b67ab5bced41111b28e962765ee7f0215 Mon Sep 17 00:00:00 2001 From: Hassan Abouelela Date: Tue, 15 Feb 2022 10:21:01 +0400 Subject: Patch `sys.__stdout__` In Code Questions Patching just `sys.stdout` allowed users to still access stdout via `sys.__stdout__`. The same was true for stderr. Both have been explicitly patched now. Signed-off-by: Hassan Abouelela --- resources/unittest_template.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/unittest_template.py b/resources/unittest_template.py index 2410278..990d077 100644 --- a/resources/unittest_template.py +++ b/resources/unittest_template.py @@ -72,12 +72,12 @@ try: DEVNULL = SimpleNamespace(write=lambda *_: None, flush=lambda *_: None) RESULT = io.StringIO() - ORIGINAL_STDOUT = sys.stdout + ORIGINAL_STDOUT = sys.__stdout__ # stdout/err is patched in order to control what is outputted by the runner - sys.stdout = DEVNULL - sys.stderr = DEVNULL - + sys.__stdout__ = sys.stdout = DEVNULL + sys.__stderr__ = sys.stderr = DEVNULL + # Load the user code as a global module variable try: module = _load_user_module() -- cgit v1.2.3 From 46341bee9b14f633e2f9580bce430438787d6a7a Mon Sep 17 00:00:00 2001 From: Hassan Abouelela Date: Tue, 15 Feb 2022 17:25:10 +0400 Subject: Handle BaseException In Code Question Change the exception handler in the unittest template to handle BaseExceptions that don't inherit from Exception. Additionally, account for user invoked system exits. Signed-off-by: Hassan Abouelela --- resources/unittest_template.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/resources/unittest_template.py b/resources/unittest_template.py index 990d077..05730ce 100644 --- a/resources/unittest_template.py +++ b/resources/unittest_template.py @@ -19,6 +19,9 @@ class RunnerTestCase(unittest.TestCase): ### UNIT CODE +normal_exit = False + + def _exit_sandbox(code: int) -> NoReturn: """ Exit the sandbox by printing the result to the actual stdout and exit with the provided code. @@ -32,6 +35,8 @@ def _exit_sandbox(code: int) -> NoReturn: 137 can also be generated by NsJail when killing the process. """ print(RESULT.getvalue(), file=ORIGINAL_STDOUT, end="") + global normal_exit + normal_exit = True sys.exit(code) @@ -81,10 +86,12 @@ try: # Load the user code as a global module variable try: module = _load_user_module() - except Exception: - RESULT.write("Uncaught exception while loading user code.") + except BaseException as e: + RESULT.write(f"Uncaught exception while loading user code: {e}") _exit_sandbox(6) _main() -except Exception: - RESULT.write("Uncaught exception inside runner.") +except BaseException as e: + if isinstance(e, SystemExit) and normal_exit: + raise e from None + RESULT.write(f"Uncaught exception inside runner: {e}") _exit_sandbox(99) -- cgit v1.2.3