Exemplo n.º 1
0
    def __init__(self, problem_id, source_code):
        super(Executor, self).__init__()
        source_code_file = self._file('%s.asm' % problem_id)
        with open(source_code_file, 'wb') as fo:
            fo.write(source_code)
        obj_file = self._file('%s.o' % problem_id)
        self._executable = output_file = self._file(str(problem_id))
        nasm_process = subprocess.Popen([
            env['runtime']['nasm'], '-f', 'elf32', source_code_file, '-o',
            obj_file
        ],
                                        stderr=subprocess.PIPE,
                                        cwd=self._dir)
        _, compile_error = nasm_process.communicate()
        if nasm_process.returncode != 0:
            raise CompileError(compile_error)

        if 'gcc' in env['runtime'] and source_code.startswith('; libc'):
            ld_process = subprocess.Popen(
                [env['runtime']['gcc'], '-m32', obj_file, '-o', output_file],
                stderr=subprocess.PIPE,
                cwd=self._dir)
        else:
            ld_process = subprocess.Popen([
                env['runtime']['ld'], '-melf_i386', '-s', obj_file, '-o',
                output_file
            ],
                                          stderr=subprocess.PIPE,
                                          cwd=self._dir)
        _, link_error = ld_process.communicate()
        if ld_process.returncode != 0:
            raise CompileError(link_error)
        self.name = problem_id
        self.warning = ('%s\n%s' % (compile_error, link_error)).strip('\n')
Exemplo n.º 2
0
 def handle_compile_error(self, output: bytes):
     if b'is public, should be declared in a file named' in utf8bytes(
             output):
         raise CompileError(
             'You are a troll. Trolls are not welcome. As a judge, I sentence your code to death.\n'
         )
     raise CompileError(output)
Exemplo n.º 3
0
 def handle_compile_error(self, output):
     if b'is public, should be declared in a file named' in utf8bytes(
             output):
         raise CompileError(
             'Public Class Error - Please use exactly one public class in your submission.\n'
         )
     raise CompileError(output)
Exemplo n.º 4
0
    def compile(self):
        object = self._file('%s.o' % self.problem)
        process = subprocess.Popen([self.as_path, '-o', object, self._code],
                                   cwd=self._dir,
                                   stderr=subprocess.PIPE)
        as_output = process.communicate()[1]
        if process.returncode != 0:
            raise CompileError(as_output)

        to_link = [object]
        if 'libc' in self.features:
            to_link = ['-dynamic-linker', self.dynamic_linker
                       ] + self.crt_pre + ['-lc'] + to_link + self.crt_post

        executable = self._file(self.problem)
        process = subprocess.Popen([self.ld_path, '-s', '-o', executable] +
                                   to_link,
                                   cwd=self._dir,
                                   stderr=subprocess.PIPE)
        ld_output = process.communicate()[1]
        if process.returncode != 0:
            raise CompileError(ld_output)

        self.warning = ('%s\n%s' % (as_output, ld_output)).strip()
        return executable
Exemplo n.º 5
0
def find_class(source):
    source = reinline_comment.sub('', restring.sub('', recomment.sub('', source)))
    class_name = reclass.search(source)
    if class_name is None:
        raise CompileError('No public class: your main class must be declared as a "public class"\n')
    package = repackage.search(source)
    if package:
        raise CompileError('Invalid package %s: do not declare package\n' % package.group(1))
    return class_name
Exemplo n.º 6
0
 def handle_compile_error(self, output):
     if b'symbol:   class Scanner' in utf8bytes(output):
         raise CompileError(
             'Te has olvidado de importar el Scanner. Has de copiar también todos los imports \n'
         )
     if b'is public, should be declared in a file named' in utf8bytes(
             output):
         raise CompileError('Solo debe haber UNA clase pública. \n')
     raise CompileError(output)
Exemplo n.º 7
0
def find_class(source):
    source = reinline_comment.sub('',
                                  restring.sub('', recomment.sub('', source)))
    class_name = reclass.search(source)
    if class_name is None:
        raise CompileError(
            'El main debe estar dentro de una public class. ¡Como si fuera Java normal!"\n'
        )
    package = repackage.search(source)
    if package:
        raise CompileError('Por favor, borra la linea del package\n')
    return class_name
Exemplo n.º 8
0
    def get_generator(self, filename, flags):
        from dmoj.executors import executors
        from dmoj.config import InvalidInitException

        filename = os.path.abspath(filename)
        cache_key = filename, tuple(flags)
        if cache_key in self._cache:
            return self._cache[cache_key]

        try:
            with open(filename) as file:
                source = file.read()
        except:
            traceback.print_exc()
            raise IOError('could not read generator source')

        def find_cpp():
            for grader in ('CPP14', 'CPP11', 'CPP0X', 'CPP'):
                if grader in executors:
                    return grader
            raise InvalidInitException(
                "can't grade with generator; why did I get this submission?")

        lookup = {
            '.py': executors.get('PY2', None),
            '.py3': executors.get('PY3', None),
            '.c': executors.get('C', None),
            '.cpp': executors.get(find_cpp(), None),
            '.java': executors.get('JAVA', None),
            '.rb': executors.get('RUBY', None)
        }
        ext = os.path.splitext(filename)[1]
        pass_platform_flags = ['.c', '.cpp']

        if pass_platform_flags:
            flags += ['-DWINDOWS_JUDGE', '-DWIN32'
                      ] if os.name == 'nt' else ['-DLINUX_JUDGE']

        clazz = lookup.get(ext, None)
        if not clazz:
            raise IOError('could not identify generator extension')
        clazz = clazz.Executor

        if hasattr(clazz, 'flags'):
            # We shouldn't be mutating the base class flags
            # See https://github.com/DMOJ/judge/issues/174
            clazz = type('FlaggedExecutor', (clazz, ),
                         {'flags': flags + list(clazz.flags)})

        try:
            # _ so we can't possibly conflict with submission source file name (e.g. /problem/generator submitted in C++)
            # _ is not a valid char in problem codes
            executor = clazz('_generator', source)
        except CompileError as err:
            # Strip ansi codes from CompileError message so we don't get wacky displays on the site like
            # 01m[K_generator.cpp:26:23:[m[K [01;31m[Kerror: [m[K'[01m[Kgets[m[K' was not declared in this scope
            raise CompileError(ansi.strip_ansi(err.message))

        self._cache[cache_key] = executor
        return executor
Exemplo n.º 9
0
    def compile(self):
        as_output, to_link = self.assemble()

        if 'libc' in self.features:
            to_link = ['-dynamic-linker', self.dynamic_linker
                       ] + self.crt_pre + ['-lc'] + to_link + self.crt_post

        executable = self._file(self.problem)
        process = TimedPopen(
            [self.get_ld_path(), '-s', '-o', executable, '-m', self.ld_m] +
            to_link,
            cwd=self._dir,
            stderr=subprocess.PIPE,
            preexec_fn=self.create_executable_limits(),
            time_limit=self.compiler_time_limit,
        )
        ld_output = process.communicate()[1]
        if process.returncode != 0:
            raise CompileError(ld_output)

        if as_output or ld_output:
            self.warning = (
                '%s\n%s' % (utf8text(as_output), utf8text(ld_output))).strip()
        self._executable = executable
        return executable
Exemplo n.º 10
0
 def __init__(self, problem_id, source_code, **kwargs):
     if self._has_invalid_brackets(source_code):
         raise CompileError(b'Unmatched brackets\n')
     code = template.replace(
         b'{code}',
         b''.join(map(trans.get, source_code, itertools.repeat(b''))))
     super().__init__(problem_id, code, **kwargs)
Exemplo n.º 11
0
    def __init__(self, problem_id, main_source, aux_sources=None):
        super(Executor, self).__init__()

        if not aux_sources:
            aux_sources = {}
        aux_sources[problem_id + '.cpp'] = main_source
        sources = []
        for name, source in aux_sources.iteritems():
            if '.' not in name:
                name += '.cpp'
            with open(self._file(name), 'wb') as fo:
                fo.write(source)
            sources.append(name)
        output_file = self._file('%s.exe' % problem_id)

        cl_args = ['cl', '-nologo'] + sources + ['-W4', '-DONLINE_JUDGE', '-DWIN32', '-D_CRT_SECURE_NO_WARNINGS',
                                                 '-EHsc', '-Ox', '-Fe%s' % output_file, '-link', '-stack:67108864']
        cl_process = subprocess.Popen(cl_args, stderr=subprocess.PIPE, executable=env['runtime']['cl.exe'],
                                      cwd=self._dir, env=VC_COMPILE)

        _, compile_error = cl_process.communicate()
        if cl_process.returncode != 0:
            raise CompileError(compile_error)
        self._executable = output_file
        self.name = problem_id
        self.warning = compile_error
Exemplo n.º 12
0
 def __init__(self, problem_id, source_code, **kwargs):
     if source_code.count(b'[') != source_code.count(b']'):
         raise CompileError(b'Unmatched brackets\n')
     code = template.replace(
         b'{code}',
         b''.join(map(trans.get, source_code, itertools.repeat(b''))))
     super(Executor, self).__init__(problem_id, code, **kwargs)
Exemplo n.º 13
0
 def create_files(self, problem_id, source_code, *args, **kwargs):
     source_code = decomment(source_code).strip()
     if source_code.split(b'\n')[0].strip().split() != [
             b'package', b'main'
     ]:
         raise CompileError(b'Your code must be defined in package main.\n')
     super(Executor, self).create_files(problem_id, source_code, *args,
                                        **kwargs)
Exemplo n.º 14
0
 def create_files(self, problem_id, source_code, *args, **kwargs):
     super().create_files(problem_id, source_code, *args, **kwargs)
     # This step is necessary because of Unicode classnames
     try:
         source_code = utf8text(source_code)
     except UnicodeDecodeError:
         raise CompileError('Your UTF-8 is bad, and you should feel bad')
     class_name = find_class(source_code)
     self._code = self._file('%s.java' % class_name.group(1))
     try:
         with open(self._code, 'wb') as fo:
             fo.write(utf8bytes(source_code))
     except IOError as e:
         if e.errno in (errno.ENAMETOOLONG, errno.ENOENT, errno.EINVAL):
             raise CompileError('Why do you need a class name so long? As a judge, I sentence your code to death.\n')
         raise
     self._class_name = class_name.group(1)
Exemplo n.º 15
0
 def compile(self):
     compile_process = subprocess.Popen(self.get_compile_args(),
                                        stderr=subprocess.STDOUT,
                                        stdout=subprocess.PIPE,
                                        cwd=self._dir)
     compile_error = compile_process.communicate()[0]
     if compile_process.returncode != 0:
         raise CompileError(compile_error)
     self.warning = compile_error
Exemplo n.º 16
0
    def assemble(self):
        object = self._file('%s.o' % self.problem)
        process = subprocess.Popen(self.get_as_args(object),
                                   cwd=self._dir,
                                   stderr=subprocess.PIPE)
        as_output = process.communicate()[1]
        if process.returncode != 0:
            raise CompileError(as_output)

        return as_output, [object]
Exemplo n.º 17
0
    def assemble(self):
        object = self._file('%s.o' % self.problem)
        process = subprocess.Popen([self.as_path, '-o', object, self._code],
                                   cwd=self._dir,
                                   stderr=subprocess.PIPE)
        as_output = process.communicate()[1]
        if process.returncode != 0:
            raise CompileError(as_output)

        return as_output, [object]
Exemplo n.º 18
0
    def get_generator(self, filename, flags):
        from dmoj.executors import executors
        from dmoj.config import InvalidInitException

        filename = os.path.abspath(filename)
        cache_key = filename, tuple(flags)
        if cache_key in self._cache:
            return self._cache[cache_key]

        try:
            with open(filename) as file:
                source = file.read()
        except:
            traceback.print_exc()
            raise IOError('could not read generator source')

        def find_cpp():
            for grader in ('CPP14', 'CPP11', 'CPP0X', 'CPP'):
                if grader in executors:
                    return grader
            raise InvalidInitException(
                "can't grade with generator; why did I get this submission?")

        lookup = {
            '.py': executors.get('PY2', None),
            '.py3': executors.get('PY3', None),
            '.c': executors.get('C', None),
            '.cpp': executors.get(find_cpp(), None),
            '.java': executors.get('JAVA', None),
            '.rb': executors.get('RUBY', None)
        }
        ext = os.path.splitext(filename)[1]
        pass_platform_flags = ['.c', '.cpp']

        if pass_platform_flags:
            flags += ['-DWINDOWS_JUDGE', '-DWIN32'
                      ] if os.name == 'nt' else ['-DLINUX_JUDGE']

        clazz = lookup.get(ext, None)
        if not clazz:
            raise IOError('could not identify generator extension')

        try:
            executor = clazz.Executor('_generator', source)
        except CompileError as err:
            # Strip ansi codes from CompileError message so we don't get wacky displays on the site like
            # 01m[K_generator.cpp:26:23:[m[K [01;31m[Kerror: [m[K'[01m[Kgets[m[K' was not declared in this scope
            raise CompileError(ansi.strip_ansi(err.message))

        if hasattr(executor, 'flags'):
            executor.flags += flags

        self._cache[cache_key] = executor
        return executor
Exemplo n.º 19
0
 def create_files(self, problem_id, source_code, *args, **kwargs):
     super().create_files(problem_id, source_code, *args, **kwargs)
     # This step is necessary because of Unicode classnames
     try:
         source_code = utf8text(source_code)
     except UnicodeDecodeError:
         raise CompileError(
             'Unicode Error - Please stick to UTF-8 characters in your submission.'
         )
     class_name = find_class(source_code)
     self._code = self._file('%s.java' % class_name.group(1))
     try:
         with open(self._code, 'wb') as fo:
             fo.write(utf8bytes(source_code))
     except IOError as e:
         if e.errno in (errno.ENAMETOOLONG, errno.ENOENT, errno.EINVAL):
             raise CompileError(
                 'Class Name Error - Please use a shorter class name.\n')
         raise
     self._class_name = class_name.group(1)
Exemplo n.º 20
0
    def get_generator(self, filenames, flags, lang=None):
        from dmoj.executors import executors

        filenames = map(os.path.abspath, filenames)
        sources = {}

        try:
            for filename in filenames:
                with open(filename, 'r') as f:
                    sources[os.path.basename(filename)] = f.read()
        except:
            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', 'CPP0X', '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 hasattr(clazz, 'flags'):
            flags += ['-DWINDOWS_JUDGE', '-DWIN32'] if os.name == 'nt' else ['-DLINUX_JUDGE']

            # We shouldn't be mutating the base class flags.
            # See <https://github.com/DMOJ/judge/issues/174>.
            clazz = type('FlaggedExecutor', (clazz,), {'flags': flags + list(clazz.flags)})

        try:
            # 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])
        except CompileError as err:
            # Strip ANSI codes from CompileError message so we don't get wacky displays on the site like
            # 01m[K_generator.cpp:26:23:[m[K [01;31m[Kerror: [m[K'[01m[Kgets[m[K' was not declared in this scope
            raise CompileError(ansi.strip_ansi(err.args[0]))

        return executor
Exemplo n.º 21
0
 def create_files(self, problem_id, source_code, *args, **kwargs):
     super(JavacExecutor, self).create_files(problem_id, source_code, *args,
                                             **kwargs)
     source_code = deunicode(source_code)
     class_name = find_class(source_code)
     self._code = self._file('%s.java' % class_name.group(1))
     try:
         with open(self._code, 'wb') as fo:
             fo.write(source_code)
     except IOError as e:
         if e.errno in (errno.ENAMETOOLONG, errno.ENOENT):
             raise CompileError(
                 'Why do you need a class name so long? '
                 'As a judge, I sentence your code to death.')
         raise
     self._class_name = class_name.group(1)
Exemplo n.º 22
0
    def _generate_binary(self):
        siggraders = ('C', 'CPP03', 'CPP0X', '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'
                                 '#define main main_%s\n') % (
                                     handler_data['header'], str(
                                         uuid.uuid4()).replace('-', ''))

            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
            try:
                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'])
            except CompileError as compilation_error:
                self.judge.packet_manager.compile_error_packet(
                    ansi.format_ansi(compilation_error.args[0]
                                     or 'compiler exited abnormally'))

                # Compile error is fatal
                raise

        self.judge.packet_manager.compile_error_packet(
            'no valid handler compiler exists')
Exemplo n.º 23
0
    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)
Exemplo n.º 24
0
    def _generate_binary(self):
        siggraders = ('C', 'CPP', 'CPP0X', 'CPP11', 'CPP14')

        for i in reversed(siggraders):
            if i in executors:
                siggrader = i
                break
        else:
            raise CompileError(
                "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_template = '''#include "%s"
#define main main_%s
%s
'''

            aux_sources[self.problem.id + '_submission'] = \
                (submission_template % (handler_data['header'], str(uuid.uuid4()).replace('-', '')), self.source)

            aux_sources[handler_data['header']] = header
            entry = entry_point
            # Compile as CPP11 regardless of what the submission language is
            try:
                return executors[siggrader].Executor(
                    self.problem.id,
                    entry,
                    aux_sources=aux_sources,
                    writable=handler_data['writable'] or (1, 2),
                    fds=handler_data['fds'])
            except CompileError as compilation_error:
                self.judge.packet_manager.compile_error_packet(
                    compilation_error.message)

                # Compile error is fatal
                raise

        self.judge.packet_manager.compile_error_packet(
            'no valid handler compiler exists')
Exemplo n.º 25
0
    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)
Exemplo n.º 26
0
    def compile(self):
        as_output, to_link = self.assemble()

        if 'libc' in self.features:
            to_link = ['-dynamic-linker', self.dynamic_linker
                       ] + self.crt_pre + ['-lc'] + to_link + self.crt_post

        executable = self._file(self.problem)
        process = self.TimedPopen(
            [self.get_ld_path(), '-s', '-o', executable, '-m', self.ld_m] +
            to_link,
            cwd=self._dir,
            stderr=subprocess.PIPE,
            preexec_fn=self.create_executable_fslimit(),
            time_limit=self.compiler_time_limit)
        ld_output = process.communicate()[1]
        if process.returncode != 0 or (hasattr(process, '_killed')
                                       and process._killed):
            raise CompileError(ld_output)

        self.warning = ('%s\n%s' % (as_output, ld_output)).strip()
        return executable
Exemplo n.º 27
0
 def handle_compile_error(self, output):
     raise CompileError(output)
Exemplo n.º 28
0
 def handle_compile_error(self, output: bytes) -> None:
     raise CompileError(output)
Exemplo n.º 29
0
 def create_files(self, problem_id, source_code, *args, **kwargs):
     source_lines = decomment(source_code).strip().split(b'\n')
     if not repackage.match(source_lines[0]):
         raise CompileError(b'Your code must be defined in package main.\n')
     super().create_files(problem_id, source_code, *args, **kwargs)
Exemplo n.º 30
0
    def __init__(self, problem_id, source_code, **kwargs):
        if resetup.search(recomment.sub('', utf8text(source_code))) is None:
            raise CompileError('You must implement "void setup()"\n')

        code = template.replace(b'{code}', source_code)
        super(Executor, self).__init__(problem_id, code, **kwargs)