def run_self_test(cls, sandbox=True, output=True, error_callback=None): if not cls.test_program: return True if output: print(ansi_style("%-39s%s" % ('Self-testing #ansi[%s](|underline):' % cls.get_executor_name(), '')), end=' ') try: executor = cls(cls.test_name, utf8bytes(cls.test_program)) proc = executor.launch(time=cls.test_time, memory=cls.test_memory) if sandbox else executor.launch_unsafe() test_message = b'echo: Hello, World!' stdout, stderr = proc.communicate(test_message + b'\n') res = stdout.strip() == test_message and not stderr if output: # Cache the versions now, so that the handshake packet doesn't take ages to generate cls.get_runtime_versions() print(ansi_style(['#ansi[Failed](red|bold)', '#ansi[Success](green|bold)'][res])) if stdout.strip() != test_message and error_callback: error_callback('Got unexpected stdout output:\n' + utf8text(stdout)) if stderr: if error_callback: error_callback('Got unexpected stderr output:\n' + utf8text(stderr)) else: print(stderr, file=sys.stderr) if hasattr(proc, 'protection_fault') and proc.protection_fault: print_protection_fault(proc.protection_fault) return res except Exception: if output: print(ansi_style('#ansi[Failed](red|bold)')) traceback.print_exc() if error_callback: error_callback(traceback.format_exc()) return False
def run_self_test( cls, output: bool = True, error_callback: Optional[Callable[[Any], Any]] = None) -> bool: if not cls.test_program: return True if output: print_ansi( f'Self-testing #ansi[{cls.get_executor_name()}](|underline):'. ljust(39), end=' ') try: executor = cls(cls.test_name, utf8bytes(cls.test_program)) proc = executor.launch(time=cls.test_time, memory=cls.test_memory, stdin=subprocess.PIPE, stdout=subprocess.PIPE) test_message = b'echo: Hello, World!' stdout, stderr = proc.communicate(test_message + b'\n') if proc.is_tle: print_ansi('#ansi[Time Limit Exceeded](red|bold)') return False if proc.is_mle: print_ansi('#ansi[Memory Limit Exceeded](red|bold)') return False res = stdout.strip() == test_message and not stderr if output: # Cache the versions now, so that the handshake packet doesn't take ages to generate cls.get_runtime_versions() usage = f'[{proc.execution_time:.3f}s, {proc.max_memory} KB]' print_ansi( f'{["#ansi[Failed](red|bold) ", "#ansi[Success](green|bold)"][res]} {usage:<19}', end=' ') print_ansi(', '.join([ f'#ansi[{runtime}](cyan|bold) {".".join(map(str, version))}' for runtime, version in cls.get_runtime_versions() ])) if stdout.strip() != test_message and error_callback: error_callback('Got unexpected stdout output:\n' + utf8text(stdout)) if stderr: if error_callback: error_callback('Got unexpected stderr output:\n' + utf8text(stderr)) else: print(stderr, file=sys.stderr) if proc.protection_fault: print_protection_fault(proc.protection_fault) return res except Exception: if output: print_ansi('#ansi[Failed](red|bold)') traceback.print_exc() if error_callback: error_callback(traceback.format_exc()) return False
def get_feedback_str(cls, error, process, binary): is_ir_or_rte = (process.is_ir or process.is_rte) and not ( process.is_tle or process.is_mle or process.is_ole) if hasattr(process, 'feedback'): feedback = process.feedback elif is_ir_or_rte: feedback = binary.parse_feedback_from_stderr(error, process) else: feedback = '' if not feedback and is_ir_or_rte: if not process.was_initialized or ( error and b'error while loading shared libraries' in error): # Process may failed to initialize, resulting in a SIGKILL without any prior signals. # See <https://github.com/DMOJ/judge/issues/179> for more details. feedback = 'failed initializing' elif process.signal: feedback = strsignal(process.signal).lower() if process.protection_fault: syscall, callname, args = process.protection_fault print_protection_fault(process.protection_fault) callname = callname.replace('sys_', '', 1) message = '%s syscall disallowed' % callname feedback = message return feedback
def update_feedback(self, check, error, process, result): result.feedback = ( check.feedback or (process.feedback if hasattr(process, 'feedback') else getattr( self.binary, 'get_feedback', lambda x, y, z: '')(error, result, process))) if not result.feedback and result.get_main_code() == Result.RTE: if hasattr(process, 'was_initialized') and not process.was_initialized: # Process may failed to initialize, resulting in a SIGKILL without any prior signals. # See <https://github.com/DMOJ/judge/issues/179> for more details. result.feedback = 'failed initializing' elif hasattr(process, 'signal'): # I suppose generate a SIGKILL message is better when we don't know the signal that caused it. result.feedback = strsignal( process.signal).lower() if process.signal else 'killed' # On Linux we can provide better help messages if hasattr(process, 'protection_fault') and process.protection_fault: syscall, callname, args = process.protection_fault print_protection_fault(process.protection_fault) callname = callname.replace('sys_', '', 1) message = { 'open': 'opening files is not allowed', }.get(callname, '%s syscall disallowed' % callname) result.feedback = message
def run_self_test( cls, output: bool = True, error_callback: Optional[Callable[[Any], Any]] = None) -> bool: if not cls.test_program: return True if output: print_ansi("%-39s%s" % ('Self-testing #ansi[%s](|underline):' % cls.get_executor_name(), ''), end=' ') try: executor = cls(cls.test_name, utf8bytes(cls.test_program)) proc = executor.launch(time=cls.test_time, memory=cls.test_memory, stdin=subprocess.PIPE, stdout=subprocess.PIPE) test_message = b'echo: Hello, World!' stdout, stderr = proc.communicate(test_message + b'\n') if proc.tle: print_ansi('#ansi[Time Limit Exceeded](red|bold)') return False if proc.mle: print_ansi('#ansi[Memory Limit Exceeded](red|bold)') return False res = stdout.strip() == test_message and not stderr if output: # Cache the versions now, so that the handshake packet doesn't take ages to generate cls.get_runtime_versions() usage = '[%.3fs, %d KB]' % (proc.execution_time, proc.max_memory) print_ansi( ['#ansi[Failed](red|bold)', '#ansi[Success](green|bold)'][res], usage) if stdout.strip() != test_message and error_callback: error_callback('Got unexpected stdout output:\n' + utf8text(stdout)) if stderr: if error_callback: error_callback('Got unexpected stderr output:\n' + utf8text(stderr)) else: print(stderr, file=sys.stderr) if proc.protection_fault: print_protection_fault(proc.protection_fault) return res except Exception: if output: print_ansi('#ansi[Failed](red|bold)') traceback.print_exc() if error_callback: error_callback(traceback.format_exc()) return False
def update_feedback(self, check, error, process, result): result.feedback = (check.feedback or (process.feedback if hasattr(process, 'feedback') else getattr(self.binary, 'get_feedback', lambda x, y, z: '')(error, result, process))) if not result.feedback and result.get_main_code() == Result.RTE: if not process.was_initialized: # Process may failed to initialize, resulting in a SIGKILL without any prior signals. # See <https://github.com/DMOJ/judge/issues/179> for more details. result.feedback = 'failed initializing' else: result.feedback = strsignal(process.signal).lower() if process.protection_fault: syscall, callname, args = process.protection_fault print_protection_fault(process.protection_fault) callname = callname.replace('sys_', '', 1) message = '%s syscall disallowed' % callname result.feedback = message
def update_feedback(self, check, error, process, result): result.feedback = (check.feedback or (process.feedback if hasattr(process, 'feedback') else getattr(self.binary, 'get_feedback', lambda x, y, z: '')(error, result, process))) if not result.feedback and result.get_main_code() == Result.RTE: if hasattr(process, 'was_initialized') and not process.was_initialized: # Process may failed to initialize, resulting in a SIGKILL without any prior signals. # See <https://github.com/DMOJ/judge/issues/179> for more details. result.feedback = 'failed initializing' elif hasattr(process, 'signal'): # I suppose generate a SIGKILL message is better when we don't know the signal that caused it. result.feedback = strsignal(process.signal).lower() if process.signal else 'killed' # On Linux we can provide better help messages if hasattr(process, 'protection_fault') and process.protection_fault: syscall, callname, args = process.protection_fault print_protection_fault(process.protection_fault) callname = callname.replace('sys_', '', 1) message = '%s syscall disallowed' % callname result.feedback = message
def run_self_test(cls, sandbox=True, output=True, error_callback=None): if not cls.test_program: return True if output: print(ansi_style("%-39s%s" % ('Self-testing #ansi[%s](|underline):' % cls.get_executor_name(), '')), end=' ') try: executor = cls(cls.test_name, utf8bytes(cls.test_program)) proc = executor.launch(time=cls.test_time, memory=cls.test_memory) if sandbox else executor.launch_unsafe() test_message = b'echo: Hello, World!' stdout, stderr = proc.communicate(test_message + b'\n') if proc.tle: print(ansi_style('#ansi[Time Limit Exceeded](red|bold)')) return False if proc.mle: print(ansi_style('#ansi[Memory Limit Exceeded](red|bold)')) return False res = stdout.strip() == test_message and not stderr if output: # Cache the versions now, so that the handshake packet doesn't take ages to generate cls.get_runtime_versions() usage = '[%.3fs, %d KB]' % (proc.execution_time, proc.max_memory) print(ansi_style(['#ansi[Failed](red|bold)', '#ansi[Success](green|bold)'][res]), usage) if stdout.strip() != test_message and error_callback: error_callback('Got unexpected stdout output:\n' + utf8text(stdout)) if stderr: if error_callback: error_callback('Got unexpected stderr output:\n' + utf8text(stderr)) else: print(stderr, file=sys.stderr) if hasattr(proc, 'protection_fault') and proc.protection_fault: print_protection_fault(proc.protection_fault) return res except Exception: if output: print(ansi_style('#ansi[Failed](red|bold)')) traceback.print_exc() if error_callback: error_callback(traceback.format_exc()) return False
def get_compile_output(self, process: TracedPopen) -> bytes: # Use safe_communicate because otherwise, malicious submissions can cause a compiler # to output hundreds of megabytes of data as output before being killed by the time limit, # which effectively murders the MySQL database waiting on the site server. limit = env.compiler_output_character_limit try: output = safe_communicate( process, None, outlimit=limit, errlimit=limit)[self.compile_output_index] except OutputLimitExceeded: output = b'compiler output too long (> 64kb)' if self.is_failed_compile(process): if process.is_tle: output = b'compiler timed out (> %d seconds)' % self.compiler_time_limit if process.protection_fault: print_protection_fault(process.protection_fault) self.handle_compile_error(output) return output