Skip to content

Sanitizers #292

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/sinol_make/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from sinol_make.task_type.interactive import InteractiveTaskType # noqa


__version__ = "1.9.7"
__version__ = "1.9.8"


def configure_parsers():
Expand Down
12 changes: 6 additions & 6 deletions src/sinol_make/commands/chkwer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def compile(self, file_path, exe_path, args, name, compilation_flags):
print(f'Compiling {name}... ', end='')
compilers = compiler.verify_compilers(args, [file_path])
exe, compile_log_path = compile.compile_file(file_path, exe_path, compilers, compilation_flags,
use_fsanitize=False, use_extras=False)
use_sanitizers=self.args.sanitize, use_extras=False)
if exe is None:
print(util.error('ERROR'))
compile.print_compile_log(compile_log_path)
Expand All @@ -57,11 +57,11 @@ def run_test(self, execution: ChkwerExecution) -> RunResult:
"""
output_file = paths.get_chkwer_path(os.path.basename(execution.out_test_path))
with open(execution.in_test_path, 'r') as inf, open(output_file, 'w') as outf:
process = subprocess.Popen([execution.model_exe], stdin=inf, stdout=outf)
process.wait()
process = subprocess.Popen([execution.model_exe], stdin=inf, stdout=outf, stderr=subprocess.PIPE)
_, stderr = process.communicate()
ok, points, comment = self.task_type.check_output(execution.in_test_path, output_file, execution.out_test_path)

return RunResult(execution.in_test_path, ok, int(points), comment)
return RunResult(execution.in_test_path, ok, int(points), comment, stderr.decode('utf-8'))

def run_and_print_table(self) -> Dict[str, TestResult]:
results = {}
Expand All @@ -84,7 +84,7 @@ def run_and_print_table(self) -> Dict[str, TestResult]:
try:
with mp.Pool(self.cpus) as pool:
for i, result in enumerate(pool.imap(self.run_test, executions)):
table_data.results[result.test_path].set_results(result.points, result.ok, result.comment)
table_data.results[result.test_path].set_results(result.points, result.ok, result.comment, result.stderr)
table_data.i = i
except KeyboardInterrupt:
keyboard_interrupt = True
Expand All @@ -99,7 +99,7 @@ def run_and_print_table(self) -> Dict[str, TestResult]:
return results

def run(self, args):
args = util.init_package_command(args)
self.args = util.init_package_command(args)
self.task_id = package_util.get_task_id()
self.task_type = package_util.get_task_type("time", None)
self.contest_type = contest_types.get_contest_type()
Expand Down
4 changes: 3 additions & 1 deletion src/sinol_make/commands/chkwer/chkwer_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ def print_line_separator():

output = []
if result.run:
if result.comment:
if result.stderr != "":
print(util.error("stderr:"), result.stderr, end=' | ')
elif result.comment:
print(result.comment)
else:
print(util.color_gray("No comment"))
Expand Down
4 changes: 2 additions & 2 deletions src/sinol_make/commands/export/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def generate_input_tests(self):
if ingen_exists(self.task_id):
ingen_path = get_ingen(self.task_id)
ingen_path = os.path.join(prog_dir, os.path.basename(ingen_path))
ingen_exe = compile_ingen(ingen_path, self.args, self.args.compile_mode)
ingen_exe = compile_ingen(ingen_path, self.args, self.args.compile_mode, use_sanitizers=self.args.sanitize)
if not run_ingen(ingen_exe, in_dir):
util.exit_with_error('Failed to run ingen.')

Expand All @@ -76,7 +76,7 @@ def generate_output_files(self):
if len(outputs) > 0:
outgen = OutgenCommand()
correct_solution_exe = compile_correct_solution(get_correct_solution(self.task_id), self.args,
self.args.compile_mode)
self.args.compile_mode, use_sanitizers=self.args.sanitize)
outgen.args = self.args
outgen.correct_solution_exe = correct_solution_exe
outgen.generate_outputs(outputs)
Expand Down
1 change: 0 additions & 1 deletion src/sinol_make/commands/gen/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ def configure_subparser(self, subparser):
parsers.add_cpus_argument(parser, 'number of cpus to use to generate output files')
parser.add_argument('-n', '--no-validate', default=False, action='store_true',
help='do not validate test contents')
parsers.add_fsanitize_argument(parser)
parsers.add_compilation_arguments(parser)
return parser

Expand Down
4 changes: 2 additions & 2 deletions src/sinol_make/commands/ingen/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ def configure_subparser(self, subparser):
parser.add_argument('-n', '--no-validate', default=False, action='store_true',
help='do not validate test contents')
parsers.add_cpus_argument(parser, 'number of cpus used for validating tests')
parsers.add_fsanitize_argument(parser)
parsers.add_compilation_arguments(parser)
return parser

Expand Down Expand Up @@ -67,7 +66,8 @@ def run(self, args: argparse.Namespace):
util.change_stack_size_to_unlimited()
self.ingen = get_ingen(self.task_id, args.ingen_path)
print(f'Using ingen file {os.path.basename(self.ingen)}')
self.ingen_exe = compile_ingen(self.ingen, self.args, self.args.compile_mode, self.args.fsanitize)
self.ingen_exe = compile_ingen(self.ingen, self.args, self.args.compile_mode,
use_sanitizers=self.args.sanitize)

previous_tests = []
try:
Expand Down
11 changes: 8 additions & 3 deletions src/sinol_make/commands/ingen/ingen_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def get_ingen(task_id, ingen_path=None):
return correct_ingen


def compile_ingen(ingen_path: str, args: argparse.Namespace, compilation_flags='default', use_fsanitize=False):
def compile_ingen(ingen_path: str, args: argparse.Namespace, compilation_flags='default', use_sanitizers='no'):
"""
Compiles ingen and returns path to compiled executable.
If ingen_path is shell script, then it will be returned.
Expand All @@ -57,7 +57,7 @@ def compile_ingen(ingen_path: str, args: argparse.Namespace, compilation_flags='

compilers = compiler.verify_compilers(args, [ingen_path])
ingen_exe, compile_log_path = compile.compile_file(ingen_path, package_util.get_executable(ingen_path),
compilers, compilation_flags, use_fsanitize=use_fsanitize,
compilers, compilation_flags, use_sanitizers=use_sanitizers,
additional_flags='-D_INGEN', use_extras=False)

if ingen_exe is None:
Expand All @@ -84,7 +84,7 @@ def run_ingen(ingen_exe, working_dir=None):
os.chmod(ingen_exe, st.st_mode | stat.S_IEXEC)

print(util.bold(' Ingen output '.center(util.get_terminal_size()[1], '=')))
process = subprocess.Popen([ingen_exe], stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
process = subprocess.Popen([ingen_exe], stdout=subprocess.PIPE, stderr=subprocess.PIPE,
cwd=working_dir, shell=is_shell)
whole_output = ''
while process.poll() is None:
Expand All @@ -98,6 +98,11 @@ def run_ingen(ingen_exe, working_dir=None):
exit_code = process.returncode
print(util.bold(' End of ingen output '.center(util.get_terminal_size()[1], '=')))

stderr = process.stderr.read()
if stderr:
print(util.error('Ingen error output:'))
print(stderr.decode('utf-8'), end='\n\n')

if util.has_sanitizer_error(whole_output, exit_code):
print(util.warning('Warning: if ingen failed due to sanitizer errors, you can either run '
'`sudo sysctl vm.mmap_rnd_bits=28` to fix this or disable sanitizers with the '
Expand Down
4 changes: 2 additions & 2 deletions src/sinol_make/commands/inwer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ def configure_subparser(self, subparser: argparse.ArgumentParser):
parser.add_argument('-t', '--tests', type=str, nargs='+',
help='test to verify, for example in/abc{0,1}*')
parsers.add_cpus_argument(parser, 'number of cpus to use when verifying tests')
parsers.add_fsanitize_argument(parser)
parsers.add_compilation_arguments(parser)
return parser

Expand Down Expand Up @@ -204,7 +203,8 @@ def run(self, args: argparse.Namespace):
print('Verifying tests: ' + util.bold(', '.join(self.tests)))

util.change_stack_size_to_unlimited()
self.inwer_executable = inwer_util.compile_inwer(self.inwer, args, args.compile_mode, args.fsanitize)
self.inwer_executable = inwer_util.compile_inwer(self.inwer, args, args.compile_mode,
use_sanitizers=args.sanitize)
results: Dict[str, TestResult] = self.verify_and_print_table()
print('')

Expand Down
4 changes: 2 additions & 2 deletions src/sinol_make/commands/inwer/inwer_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ def get_inwer_path(task_id: str, path=None) -> Union[str, None]:
return None


def compile_inwer(inwer_path: str, args: argparse.Namespace, compilation_flags='default', use_fsanitize=False):
def compile_inwer(inwer_path: str, args: argparse.Namespace, compilation_flags='default', use_sanitizers='no'):
"""
Compiles inwer and returns path to compiled executable and path to compile log.
"""
compilers = compiler.verify_compilers(args, [inwer_path])
inwer_exe, compile_log_path = compile.compile_file(inwer_path, package_util.get_executable(inwer_path), compilers,
compilation_flags, use_fsanitize=use_fsanitize,
compilation_flags, use_sanitizers=use_sanitizers,
additional_flags='-D_INWER', use_extras=False)

if inwer_exe is None:
Expand Down
13 changes: 9 additions & 4 deletions src/sinol_make/commands/outgen/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,16 @@ def generate_outputs(self, outputs_to_generate):

with mp.Pool(self.args.cpus) as pool:
results = []
for i, result in enumerate(pool.imap(generate_output, arguments)):
for i, (result, stderr) in enumerate(pool.imap(generate_output, arguments)):
results.append(result)
output_file = os.path.basename(arguments[i].output_test)
if stderr:
print(util.error(f'Outgen stderr on {output_file}:'))
print(stderr.decode('utf-8'), end='\n\n')
if result:
print(f'Successfully generated output file {os.path.basename(arguments[i].output_test)}')
print(f'Successfully generated output file {output_file}')
else:
print(util.error(f'Failed to generate output file {os.path.basename(arguments[i].output_test)}'))
print(util.error(f'Failed to generate output file {output_file}'))

if not all(results):
util.exit_with_error('Failed to generate some output files.')
Expand Down Expand Up @@ -123,7 +127,8 @@ def run(self, args: argparse.Namespace):
else:
self.clean_cache(from_inputs)
self.correct_solution_exe = compile_correct_solution(self.correct_solution, self.args,
self.args.compile_mode)
self.args.compile_mode,
use_sanitizers=self.args.sanitize)
self.generate_outputs(outputs_to_generate)
with open(os.path.join(os.getcwd(), 'in', '.md5sums'), 'w') as f:
yaml.dump(md5_sums, f)
Expand Down
10 changes: 5 additions & 5 deletions src/sinol_make/commands/outgen/outgen_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ def get_correct_solution(task_id):
return correct_solution[0]


def compile_correct_solution(solution_path: str, args: argparse.Namespace, compilation_flags='default'):
def compile_correct_solution(solution_path: str, args: argparse.Namespace, compilation_flags='default', use_sanitizers='no'):
"""
Compiles correct solution and returns path to compiled executable.
"""
compilers = compiler.verify_compilers(args, [solution_path])
correct_solution_exe, compile_log_path = compile.compile_file(solution_path, package_util.get_executable(solution_path), compilers,
compilation_flags)
compilation_flags, use_sanitizers=use_sanitizers)
if correct_solution_exe is None:
util.exit_with_error('Failed compilation of correct solution.',
lambda: compile.print_compile_log(compile_log_path))
Expand All @@ -49,7 +49,7 @@ def generate_output(arguments):

input_file = open(input_test, 'r')
output_file = open(output_test, 'w')
process = subprocess.Popen([correct_solution_exe], stdin=input_file, stdout=output_file, preexec_fn=os.setsid)
process = subprocess.Popen([correct_solution_exe], stdin=input_file, stdout=output_file, stderr=subprocess.PIPE, preexec_fn=os.setsid)
previous_sigint_handler = signal.getsignal(signal.SIGINT)

def sigint_handler(signum, frame):
Expand All @@ -60,10 +60,10 @@ def sigint_handler(signum, frame):
sys.exit(1)
signal.signal(signal.SIGINT, sigint_handler)

process.wait()
_, stderr = process.communicate()
signal.signal(signal.SIGINT, previous_sigint_handler)
exit_code = process.returncode
input_file.close()
output_file.close()

return exit_code == 0
return exit_code == 0, stderr
7 changes: 5 additions & 2 deletions src/sinol_make/commands/run/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,9 @@ def configure_subparser(self, subparser):
help='allow running the script without full outputs')
parser.add_argument('-o', '--comments', dest='comments', action='store_true',
help="show checker's comments")
parsers.add_compilation_arguments(parser)
parsers.add_compilation_arguments(parser, custom_sanitize_help='When using sanitizers, make sure '
'that you are running with `time` tool for measuring time and memory. '
'Sio2jail does not support sanitizers.')
return parser

def extract_file_name(self, file_path):
Expand Down Expand Up @@ -365,7 +367,8 @@ def compile(self, solution, dest=None, use_extras=False, clear_cache=False, name
try:
with open(compile_log_file, "w") as compile_log:
compile.compile(source_file, output, self.compilers, compile_log, self.args.compile_mode,
extra_compilation_args, extra_compilation_files, clear_cache=clear_cache)
extra_compilation_args, extra_compilation_files, clear_cache=clear_cache,
use_sanitizers=self.args.sanitize)
print(util.info(f"Compilation of {name} was successful."))
return True
except CompilationError as e:
Expand Down
2 changes: 1 addition & 1 deletion src/sinol_make/helpers/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def get_cache_file(solution_path: str) -> CacheFile:
return CacheFile()


def check_compiled(file_path: str, compilation_flags: str, sanitizers: bool) -> Union[str, None]:
def check_compiled(file_path: str, compilation_flags: str, sanitizers: str) -> Union[str, None]:
"""
Check if a file is compiled
:param file_path: Path to the file
Expand Down
Loading
Loading