def parse_return_code(cls, proc, executor, point_value, time_limit, memory_limit, feedback, name, stderr): if proc.returncode == cls.AC: return CheckerResult(True, point_value, feedback=feedback) elif proc.returncode == cls.PARTIAL: match = cls.repartial.search(stderr) if not match: raise InternalError('Invalid stderr for partial points: %r' % stderr) points = int(match.group(1)) if not 0 <= points <= point_value: raise InternalError('Invalid partial points: %d' % points) return CheckerResult(True, points, feedback=feedback) elif proc.returncode == cls.WA: return CheckerResult(False, 0, feedback=feedback) elif proc.returncode == cls.PE: return CheckerResult(False, 0, feedback=feedback or 'Presentation Error') elif proc.returncode == cls.IE: raise InternalError('%s failed assertion with message %s' % (name, feedback)) else: parse_helper_file_error(proc, executor, name, stderr, time_limit, memory_limit)
def check(process_output: bytes, judge_output: bytes, point_value: float = 1, point_distribution: List[int] = [1], filler_lines_required: bool = True, **kwargs) -> Union[CheckerResult, bool]: judge_lines = list( filter(None, resplit(b'[\r\n]', utf8bytes(judge_output)))) if len(judge_lines) != len(point_distribution): raise InternalError( 'point distribution length must equal to judge output length') if sum(point_distribution) == 0: raise InternalError('sum of point distribution must be positive') process_lines = list( filter(None, resplit(b'[\r\n]', utf8bytes(process_output)))) if filler_lines_required and len(process_lines) != len(judge_lines): return False points = 0 for process_line, judge_line, line_points in zip(process_lines, judge_lines, point_distribution): if process_line == judge_line: points += line_points return CheckerResult(points > 0, point_value * (points / sum(point_distribution)))
def _run_generator(self, gen, args=None): flags = [] args = args or [] # resource limits on how to run the generator time_limit = env.generator_time_limit memory_limit = env.generator_memory_limit use_sandbox = env.generator_sandboxing base = get_problem_root(self.problem.id) if isinstance(gen, six.string_types): filename = os.path.join(base, gen) else: filename = os.path.join(base, gen.source) if gen.flags: flags += gen.flags if not args and gen.args: args += gen.args time_limit = gen.time_limit or time_limit memory_limit = gen.memory_limit or memory_limit # Optionally allow disabling the sandbox if gen.use_sandbox is not None: use_sandbox = gen.use_sandbox executor = self.problem.generator_manager.get_generator(filename, flags) # convert all args to str before launching; allows for smoother int passing args = map(str, args) # we allow both "trusted" and "untrusted" generators, for different scenarios: # e.g., an untrusted generator may be one generated via site-managed data by an # arbitrary user, who shouldn't be allowed to do arbitrary things on the host machine if use_sandbox: # setting large buffers is really important, because otherwise stderr is unbuffered # and the generator begins calling into cptbox Python code really frequently proc = executor.launch(*args, time=time_limit, memory=memory_limit, pipe_stderr=True, stderr_buffer_size=65536, stdout_buffer_size=65536) else: proc = executor.launch_unsafe(*args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) try: input = self.problem.problem_data[self.config['in']] if self.config['in'] else None except KeyError: input = None self._generated = list(map(self._normalize, proc.communicate(input))) if hasattr(proc, 'tle') and proc.tle: raise InternalError('generator timed out (> %s seconds)' % time_limit) if hasattr(proc, 'mle') and proc.mle: raise InternalError('generator ran out of memory (> %s Kb)' % memory_limit) if hasattr(proc, 'protection_fault') and proc.protection_fault: syscall, callname, args = proc.protection_fault raise InternalError('generator invoked disallowed syscall %s (%s)' % (syscall, callname)) if proc.returncode: raise InternalError('generator exited with nonzero code: %s' % proc.returncode)
def get_executor(checker_kwargs, problem_id): global executor if executor is None: if 'files' not in checker_kwargs: raise InternalError('no checker file(s) specified!') if 'lang' not in checker_kwargs: raise InternalError('language not specified for checker!') filenames = list(map(lambda x: os.path.join(get_problem_root(problem_id), x), checker_kwargs['files'])) lang = checker_kwargs['lang'] executor = compile_with_auxiliary_files(filenames, lang, checker_kwargs['compiler_time_limit']) return executor
def parse_feedback_from_stderr(self, stderr: bytes, process: TracedPopen) -> str: if process.returncode: assert self._dir is not None try: with open(os.path.join(self._dir, 'submission_jvm_crash.log'), 'r') as err: log = err.read() # "Newer" (post-Java 8) JVMs regressed a bit in terms of handling out-of-memory situations during # initialization, whereby they now dump a crash log rather than exiting with # java.lang.OutOfMemoryError. Handle this case so that we don't erroneously emit internal errors. if 'There is insufficient memory for the Java Runtime' in log: return 'insufficient memory to initialize JVM' else: raise InternalError('\n\n' + log) except IOError: pass if b'Error: Main method not found in class' in stderr: exception = 'public static void main(String[] args) not found' else: match = deque(reexception.finditer(utf8text(stderr, 'replace')), maxlen=1) if not match: exception = 'abnormal termination' # Probably exited without calling shutdown hooks else: exception = match[0].group(1).split(':')[0] return exception
def _protection_fault(self, syscall): # When signed, 0xFFFFFFFF is equal to -1, meaning that ptrace failed to read the syscall for some reason. # We can't continue debugging as this could potentially be unsafe, so we should exit loudly. # See <https://github.com/DMOJ/judge/issues/181> for more details. if syscall == 0xFFFFFFFF: raise InternalError('ptrace failed') # TODO: this would be more useful if we had access to a proper errno # import errno, os # err = ... # raise InternalError('ptrace error: %d (%s: %s)' % (err, errno.errorcode[err], os.strerror(err))) else: callname = 'unknown' index = self._syscall_index for id, call in enumerate(translator): if call[index] == syscall: callname = by_id[id] break print >> sys.stderr, 'Protection fault on: %d (%s)' % (syscall, callname) print >> sys.stderr, 'Arg0: 0x%016x' % self.debugger.uarg0 print >> sys.stderr, 'Arg1: 0x%016x' % self.debugger.uarg1 print >> sys.stderr, 'Arg2: 0x%016x' % self.debugger.uarg2 print >> sys.stderr, 'Arg3: 0x%016x' % self.debugger.uarg3 print >> sys.stderr, 'Arg4: 0x%016x' % self.debugger.uarg4 print >> sys.stderr, 'Arg5: 0x%016x' % self.debugger.uarg5 self.protection_fault = (syscall, callname)
def parse_return_code(cls, proc, executor, point_value, time_limit, memory_limit, feedback, name, stderr): if proc.returncode == cls.PARTIAL: match = cls.repartial.search(stderr) if not match: raise InternalError( 'Invalid stderr for fraction of points: %r' % stderr) percentage = int(match.group(2)) / int(match.group(3)) if not 0.0 <= percentage <= 1.0: raise InternalError('Invalid fraction: %s' % match.group(1)) points = percentage * point_value return CheckerResult(True, points, feedback=feedback) else: return super().parse_return_code(proc, executor, point_value, time_limit, memory_limit, feedback, name, stderr)
def check(process_output, judge_output, split_on='lines', **kwargs): split_pattern = { 'lines': b'[\r\n]', 'whitespace': b'[\s]', }.get(split_on) if not split_pattern: raise InternalError('invalid `split_on` mode') process_lines = list( filter(None, resplit(split_pattern, utf8bytes(process_output)))) judge_lines = list( filter(None, resplit(split_pattern, utf8bytes(judge_output)))) if len(process_lines) != len(judge_lines): return False if split_on == 'lines': process_lines = list(map(six.binary_type.split, process_lines)) judge_lines = list(map(six.binary_type.split, judge_lines)) process_lines.sort() judge_lines.sort() for process_line, judge_line in zip(process_lines, judge_lines): if process_line != judge_line: return False return True
def parse_feedback_from_stderr(self, stderr, process): if process.returncode: try: with open(os.path.join(self._dir, 'submission_jvm_crash.log'), 'r') as err: log = err.read() # "Newer" (post-Java 8) JVMs regressed a bit in terms of handling out-of-memory situations during # initialization, whereby they now dump a crash log rather than exiting with # java.lang.OutOfMemoryError. Handle this case so that we don't erroneously emit internal errors. if 'There is insufficient memory for the Java Runtime' in log: return 'insufficient memory to initialize JVM' else: raise InternalError('\n\n' + log) except IOError: pass if b'Error: Main method not found in class' in stderr: exception = "public static void main(String[] args) not found" else: print("AQUEST ES EL STDERR", str(stderr)) match = deque(reexception.finditer(utf8text(stderr, 'replace')), maxlen=1) linea = str(stderr).split(':')[-1].split(')')[0] print(linea) if not match: exception = "El teu codi ha petat sense donar excepció. Això es tecnicament impossible que passi, així que si passa ensenya-li això al Marc i es rascarà el cap mentre diu -Pero això és impossible que passi!- " # Probably exited without calling shutdown hooks elif "AccessControlException" in match[0].group(1).split(':')[0]: exception = ( "Has intentat hackejar-me. Et sentencio a mort.\n") else: exception = match[0].group(1).split( ':')[0] + " en línea " + linea return exception
def __init__(self, judge, problem, language, source): super().__init__(judge, problem, language, source) self.handler_data = self.problem.config.interactive self.interactor_binary = self._generate_interactor_binary() self.contrib_type = self.handler_data.get('type', 'default') if self.contrib_type not in contrib_modules: raise InternalError('%s is not a valid contrib module' % self.contrib_type)
class BridgedInteractiveGrader(StandardGrader): def __init__(self, judge, problem, language, source): super().__init__(judge, problem, language, source) self.handler_data = self.problem.config.interactive self.interactor_binary = self._generate_interactor_binary() def check_result(self, case, result): if result.result_flag: # This is usually because of a TLE verdict raised after the interactor # has issued the AC verdict # This results in a TLE verdict getting full points, which should not be the case return False stderr = self._interactor.stderr.read() return_code = self.handler_data.get('type', 'default') if return_code not in contrib_modules: raise InternalError('%s is not a valid return code parser' % return_code) return contrib_modules[return_code].ContribModule.parse_return_code( self._interactor, self.interactor_binary, case.points, self._interactor_time_limit, self._interactor_memory_limit, feedback=utf8text(stderr) if self.handler_data.feedback else None, name='interactor', stderr=stderr)
def _generate_binary(self): siggraders = ('C', 'C11', 'CPP03', 'CPP11', 'CPP14', 'CPP17', 'CLANG', 'CLANGX') if self.language in siggraders: aux_sources = {} handler_data = self.problem.config['signature_grader'] entry_point = self.problem.problem_data[handler_data['entry']] header = self.problem.problem_data[handler_data['header']] submission_prefix = '#include "%s"\n' % handler_data['header'] if not handler_data.get('allow_main', False): submission_prefix += '#define main main_%s\n' % uuid.uuid4( ).hex aux_sources[ self.problem.id + '_submission'] = utf8bytes(submission_prefix) + self.source aux_sources[handler_data['header']] = header entry = entry_point return executors[self.language].Executor( self.problem.id, entry, aux_sources=aux_sources, defines=['-DSIGNATURE_GRADER'], ) else: raise InternalError( 'no valid runtime for signature grading %s found' % self.language)
def compile_with_auxiliary_files(filenames, flags=[], lang=None, compiler_time_limit=None, should_cache=True): from dmoj.executors import executors from dmoj.executors.compiled_executor import CompiledExecutor sources = {} for filename in filenames: with open(filename, 'rb') as f: sources[os.path.basename(filename)] = f.read() def find_runtime(languages): for grader in languages: if grader in executors: return grader return None use_cpp = any( map(lambda name: os.path.splitext(name)[1] in ['.cpp', '.cc'], filenames)) use_c = any( map(lambda name: os.path.splitext(name)[1] in ['.c'], filenames)) if lang is None: best_choices = ('CPP20', 'CPP17', 'CPP14', 'CPP11', 'CPP03') if use_cpp else ('C11', 'C') lang = find_runtime(best_choices) executor = executors.get(lang) if not executor: raise IOError('could not find an appropriate C++ executor') executor = executor.Executor kwargs = {'fs': executor.fs + [tempfile.gettempdir()]} if issubclass(executor, CompiledExecutor): kwargs['compiler_time_limit'] = compiler_time_limit if hasattr(executor, 'flags'): kwargs['flags'] = flags + list(executor.flags) # Optimize the common case. if use_cpp or use_c: # Some auxiliary files (like those using testlib.h) take an extremely long time to compile, so we cache them. executor = executor('_aux_file', None, aux_sources=sources, cached=should_cache, **kwargs) else: if len(sources) > 1: raise InternalError( 'non-C/C++ auxilary programs cannot be multi-file') executor = executor('_aux_file', list(sources.values())[0], **kwargs) return executor
def check( process_output, judge_output, judge_input, problem_id, files, lang, time_limit=env['generator_time_limit'], memory_limit=env['generator_memory_limit'], compiler_time_limit=env['generator_compiler_limit'], feedback=True, flags=[], type='default', args_format_string=None, point_value=None, **kwargs, ) -> CheckerResult: executor = get_executor(problem_id, files, flags, lang, compiler_time_limit) if type not in contrib_modules: raise InternalError('%s is not a valid contrib module' % type) args_format_string = args_format_string or contrib_modules[ type].ContribModule.get_checker_args_format_string() with mktemp(judge_input) as input_file, mktemp( process_output) as output_file, mktemp( judge_output) as answer_file: checker_args = shlex.split( args_format_string.format( input_file=shlex.quote(input_file.name), output_file=shlex.quote(output_file.name), answer_file=shlex.quote(answer_file.name), )) process = executor.launch( *checker_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, memory=memory_limit, time=time_limit, ) proc_output, error = process.communicate() proc_output = utf8text(proc_output) return contrib_modules[type].ContribModule.parse_return_code( process, executor, point_value, time_limit, memory_limit, feedback=utf8text(proc_output) if feedback else '', name='checker', stderr=error, )
def get_generator(self, filenames, flags, lang=None, compiler_time_limit=None): from dmoj.executors import executors from dmoj.executors.compiled_executor import CompiledExecutor filenames = list(map(os.path.abspath, filenames)) sources = {} try: for filename in filenames: with open(filename, 'rb') as f: sources[os.path.basename(filename)] = f.read() except Exception: traceback.print_exc() raise IOError('could not read generator source') def find_runtime(languages): for grader in languages: if grader in executors: return grader return None use_cpp = any( map(lambda name: os.path.splitext(name)[1] == '.cpp', filenames)) if lang is None: best_choices = ('CPP17', 'CPP14', 'CPP11', 'CPP03') if use_cpp else ('C11', 'C') lang = find_runtime(best_choices) clazz = executors.get(lang) if not clazz: raise IOError('could not find a C++ executor for generator') clazz = clazz.Executor if issubclass(clazz, CompiledExecutor): compiler_time_limit = compiler_time_limit or clazz.compiler_time_limit clazz = type('Executor', (clazz, ), {'compiler_time_limit': compiler_time_limit}) # Optimize the common case. if use_cpp: # Some generators (like those using testlib.h) take an extremely long time to compile, so we cache them. executor = clazz('_generator', None, aux_sources=sources, cached=True) else: if len(sources) > 1: raise InternalError('non-C/C++ generator cannot be multi-file') executor = clazz('_generator', list(sources.values())[0]) return executor
def parse_return_code(cls, proc, executor, point_value, time_limit, memory_limit, feedback, name, stderr): if proc.returncode == cls.AC: return CheckerResult(True, point_value, feedback=feedback) elif proc.returncode == cls.PARTIAL: match = cls.repartial.search(stderr) if not match: raise InternalError('Invalid stderr for partial points: %r' % stderr) points = float(match.group(0)) if not 0 <= points <= 1: raise InternalError('Invalid partial points: %d' % points) ac = (points == 1) return CheckerResult(ac, points * point_value, feedback=feedback) elif proc.returncode == cls.WA: return CheckerResult(False, 0, feedback=feedback) else: parse_helper_file_error(proc, executor, name, stderr, time_limit, memory_limit)
def launch(self, *args, **kwargs) -> TracedPopen: assert self._dir is not None for src, dst in kwargs.get('symlinks', {}).items(): src = os.path.abspath(os.path.join(self._dir, src)) # Disallow the creation of symlinks outside the submission directory. if os.path.commonprefix([src, self._dir]) == self._dir: # If a link already exists under this name, it's probably from a # previous case, but might point to something different. if os.path.islink(src): os.unlink(src) os.symlink(dst, src) else: raise InternalError( 'cannot symlink outside of submission directory') agent = self._file('setbufsize.so') # Hardcode the ABIs for different executors for now if self.name == 'CPP17X': shutil.copyfile(setbufsize32_path, agent) elif self.name == 'TUR': shutil.copyfile(setbufsize86_path, agent) else: shutil.copyfile(setbufsize_path, agent) env = { # Forward LD_LIBRARY_PATH for systems (e.g. Android Termux) that require # it to find shared libraries 'LD_LIBRARY_PATH': os.environ.get('LD_LIBRARY_PATH', ''), 'LD_PRELOAD': agent, 'CPTBOX_STDOUT_BUFFER_SIZE': kwargs.get('stdout_buffer_size'), 'CPTBOX_STDERR_BUFFER_SIZE': kwargs.get('stderr_buffer_size'), } env.update(self.get_env()) executable = self.get_executable() assert executable is not None return TracedPopen( [utf8bytes(a) for a in self.get_cmdline(**kwargs) + list(args)], executable=utf8bytes(executable), security=self.get_security(launch_kwargs=kwargs), address_grace=self.get_address_grace(), data_grace=self.data_grace, personality=self.personality, time=kwargs.get('time', 0), memory=kwargs.get('memory', 0), wall_time=kwargs.get('wall_time'), stdin=kwargs.get('stdin'), stdout=kwargs.get('stdout'), stderr=kwargs.get('stderr'), env=env, cwd=utf8bytes(self._dir), nproc=self.get_nproc(), fsize=self.fsize, )
def check(proc_output, judge_output, judge_input, point_value, submission_source, **kwargs): try: proc_output = utf8text(proc_output) judge_input = utf8text(judge_input) judge_output = utf8text(judge_output) submission_source = utf8text(submission_source).replace('\r', '') except (AssertionError, ValueError, IndexError, TypeError, OverflowError): return False except Exception as e: raise InternalError('Error in checker - ' + str(e))
def check(process_output, judge_output, judge_input, checker_kwargs, problem_id, point_value=None, **kwargs) -> CheckerResult: # Update checker_kwargs with defaults for key, value in checker_defaults.items(): checker_kwargs.setdefault(key, value) executor = get_executor(checker_kwargs, problem_id) with mktemp(judge_input) as input_file, mktemp( process_output) as output_file, mktemp(judge_output) as judge_file: process = executor.launch(input_file.name, output_file.name, judge_file.name, stdout=subprocess.PIPE, stderr=subprocess.PIPE, memory=checker_kwargs['memory_limit'], time=checker_kwargs['time_limit']) proc_output, error = map(utf8text, process.communicate()) # We use the testlib.h return codes AC = 0 WA = 1 PE = 2 IE = 3 if process.returncode == AC: if checker_kwargs['feedback']: return CheckerResult(True, point_value, feedback=proc_output) else: return CheckerResult(True, point_value) elif process.returncode in (WA, PE): if checker_kwargs['feedback']: return CheckerResult(False, 0, feedback=proc_output) else: return CheckerResult(False, 0, feedback='Presentation Error' if process.returncode == PE else '') else: if process.returncode == IE: error = 'checker failed assertion with message %s' % proc_output else: error = 'checker returned unexpected return code %d with stderr %s' % ( process.returncode, error) raise InternalError(error)
def check(process_output, judge_output, judge_input, problem_id, files, lang, time_limit=env['generator_time_limit'], memory_limit=env['generator_memory_limit'], compiler_time_limit=env['generator_compiler_limit'], feedback=True, point_value=None, **kwargs) -> CheckerResult: executor = get_executor(files, lang, compiler_time_limit, problem_id) with mktemp(judge_input) as input_file, mktemp( process_output) as output_file, mktemp(judge_output) as judge_file: process = executor.launch(input_file.name, output_file.name, judge_file.name, stdout=subprocess.PIPE, stderr=subprocess.PIPE, memory=memory_limit, time=time_limit) proc_output, error = map(utf8text, process.communicate()) # We use the testlib.h return codes AC = 0 WA = 1 PE = 2 IE = 3 if process.returncode == AC: if feedback: return CheckerResult(True, point_value, feedback=proc_output) else: return CheckerResult(True, point_value) elif process.returncode in (WA, PE): if feedback: return CheckerResult(False, 0, feedback=proc_output) else: return CheckerResult(False, 0, feedback='Presentation Error' if process.returncode == PE else '') else: if process.returncode == IE: error = 'checker failed assertion with message %s' % proc_output else: error = 'checker returned unexpected return code %d with stderr %s' % ( process.returncode, error) raise InternalError(error)
def check(process_output: bytes, judge_output: bytes, precision: int = 6, error_mode: str = 'default', **kwargs) -> bool: # Discount empty lines process_lines = list( filter(None, resplit(b'[\r\n]', utf8bytes(process_output)))) judge_lines = list( filter(None, resplit(b'[\r\n]', utf8bytes(judge_output)))) if len(process_lines) != len(judge_lines): return False verify_float = { 'absolute': verify_absolute, 'relative': verify_relative, 'default': verify_default, }.get(error_mode) if not verify_float: raise InternalError('invalid `error_mode` value') epsilon = 10**-int(precision) try: for process_line, judge_line in zip(process_lines, judge_lines): process_tokens = process_line.split() judge_tokens = judge_line.split() if len(process_tokens) != len(judge_tokens): return False for process_token, judge_token in zip(process_tokens, judge_tokens): # Allow mixed tokens, for lines like "abc 0.68 def 0.70" try: judge_float = float(judge_token) except ValueError: # If it's not a float the token must match exactly if process_token != judge_token: return False else: process_float = float(process_token) if not verify_float(process_float, judge_float, epsilon): return False except Exception: return False return True
def _protection_fault(self, syscall): # When signed, 0xFFFFFFFF is equal to -1, meaning that ptrace failed to read the syscall for some reason. # We can't continue debugging as this could potentially be unsafe, so we should exit loudly. # See <https://github.com/DMOJ/judge/issues/181> for more details. if syscall == 0xFFFFFFFF: raise InternalError('ptrace failed') # TODO: this would be more useful if we had access to a proper errno # import errno, os # err = ... # raise InternalError('ptrace error: %d (%s: %s)' % (err, errno.errorcode[err], os.strerror(err))) else: callname = self.debugger.get_syscall_name(syscall) self.protection_fault = (syscall, callname, [self.debugger.uarg0, self.debugger.uarg1, self.debugger.uarg2, self.debugger.uarg3, self.debugger.uarg4, self.debugger.uarg5])
def parse_return_code(cls, proc, executor, point_value, time_limit, memory_limit, feedback, name, stderr): if proc.returncode == cls.AC: return CheckerResult(True, point_value, feedback=feedback) elif proc.returncode == cls.WA: return CheckerResult(False, 0, feedback=feedback) elif proc.returncode == cls.PE: return CheckerResult(False, 0, feedback=feedback or 'Presentation Error') elif proc.returncode == cls.IE: raise InternalError('%s failed assertion with message %s' % (name, feedback)) else: parse_helper_file_error(proc, executor, name, stderr, time_limit, memory_limit)
def get_feedback(self, stderr, result, process): if process.returncode: try: with open(os.path.join(self._dir, 'submission_jvm_crash.log'), 'r') as err: raise InternalError('\n\n' + err.read()) except IOError: pass if not result.result_flag & Result.IR or not stderr or len( stderr) > 2048: return '' match = deque(reexception.finditer(stderr), maxlen=1) if not match: return '' exception = match[0].group(1).strip() return exception
def check(process_output, judge_output, judge_input, problem_id, files, lang, time_limit=env['generator_time_limit'], memory_limit=env['generator_memory_limit'], compiler_time_limit=env['generator_compiler_limit'], feedback=True, flags=[], cached=True, type='default', point_value=None, **kwargs) -> CheckerResult: executor = get_executor(problem_id, files, flags, lang, compiler_time_limit, cached) if type not in contrib_modules: raise InternalError('%s is not a valid return code parser' % type) with mktemp(judge_input) as input_file, mktemp( process_output) as output_file, mktemp(judge_output) as judge_file: process = executor.launch( input_file.name, output_file.name, judge_file.name, stdout=subprocess.PIPE, stderr=subprocess.PIPE, memory=memory_limit, time=time_limit, ) proc_output, error = process.communicate() proc_output = utf8text(proc_output) return contrib_modules[type].ContribModule.parse_return_code( process, executor, point_value, time_limit, memory_limit, feedback=utf8text(proc_output) if feedback else None, name='checker', stderr=error, )
def get_feedback(self, stderr, result, process): if process.returncode: try: with open(os.path.join(self._dir, 'submission_jvm_crash.log'), 'r') as err: raise InternalError('\n\n' + err.read()) except IOError: pass if not result.result_flag & Result.IR: return '' try: with open(os.path.join(self._dir, 'state'), 'r') as state: exception = state.read().strip() except IOError: exception = "abnormal termination" # Probably exited without calling shutdown hooks return exception
def _generate_binary(self): siggraders = ('C', 'C11', 'CPP03', 'CPP11', 'CPP14', 'CPP17') for i in reversed(siggraders): if i in executors: siggrader = i break else: raise CompileError( b"can't signature grade, why did I get this submission?") if self.language in siggraders: aux_sources = {} handler_data = self.problem.config['signature_grader'] entry_point = self.problem.problem_data[handler_data['entry']] header = self.problem.problem_data[handler_data['header']] # fmt: off submission_prefix = ('#include "%s"\n' '#define main main_%s\n') % ( handler_data['header'], str( uuid.uuid4()).replace('-', '')) # fmt: on aux_sources[ self.problem.id + '_submission'] = utf8bytes(submission_prefix) + self.source aux_sources[handler_data['header']] = header entry = entry_point # Compile as CPP regardless of what the submission language is return executors[siggrader].Executor( self.problem.id, entry, aux_sources=aux_sources, writable=handler_data['writable'] or (1, 2), fds=handler_data['fds'], defines=['-DSIGNATURE_GRADER'], ) else: raise InternalError( 'no valid runtime for signature grading %s found' % self.language)
def parse_helper_file_error(proc, executor, name, stderr, time_limit, memory_limit): if proc.is_tle: error = '%s timed out (> %d seconds)' % (name, time_limit) elif proc.is_mle: error = '%s ran out of memory (> %s Kb)' % (name, memory_limit) elif proc.protection_fault: syscall, callname, args = proc.protection_fault error = '%s invoked disallowed syscall %s (%s)' % (name, syscall, callname) elif proc.returncode: if proc.returncode > 0: error = '%s exited with nonzero code %d' % (name, proc.returncode) else: error = '%s exited with %s' % (name, strsignal(proc.signal)) feedback = Result.get_feedback_str(stderr, proc, executor) if feedback: error += ' with feedback %s' % feedback else: return raise InternalError(error)
def get_feedback(self, stderr, result, process): if process.returncode: try: with open(os.path.join(self._dir, 'submission_jvm_crash.log'), 'r') as err: raise InternalError('\n\n' + err.read()) except IOError: pass if not result.result_flag & Result.IR: return '' if b'Error: Main method not found in class' in stderr: exception = "public static void main(String[] args) not found" else: match = deque(reexception.finditer(utf8text(stderr, 'replace')), maxlen=1) if not match: exception = "abnormal termination" # Probably exited without calling shutdown hooks else: exception = match[0].group(1).split(':')[0] return exception
def _generate_binary(self): siggraders = ('C', 'C11', 'CPP03', 'CPP11', 'CPP14', 'CPP17') for i in reversed(siggraders): if i in executors: siggrader = i break else: raise CompileError( b"can't signature grade, why did I get this submission?") if self.language in siggraders: aux_sources = {} handler_data = self.problem.config['signature_grader'] entry_point = self.problem.problem_data[handler_data['entry']] header = self.problem.problem_data[handler_data['header']] submission_prefix = '#include "%s"\n' % handler_data['header'] if not handler_data.get('allow_main', False): submission_prefix += '#define main main_%s\n' % uuid.uuid4( ).hex aux_sources[ self.problem.id + '_submission'] = utf8bytes(submission_prefix) + self.source aux_sources[handler_data['header']] = header entry = entry_point # Compile as CPP regardless of what the submission language is return executors[siggrader].Executor( self.problem.id, entry, aux_sources=aux_sources, defines=['-DSIGNATURE_GRADER'], ) else: raise InternalError( 'no valid runtime for signature grading %s found' % self.language)