From 30f5fa435bcc3ebb3e0e22ecf01d3b97ac9dd4e0 Mon Sep 17 00:00:00 2001 From: "pixl.dt" Date: Tue, 20 Dec 2022 21:45:32 +0100 Subject: [PATCH 1/3] Fix for issue #123 Make the testrun controller check whether the input file is a zip by extension only and saves that information in the model. Change a downloaded zipped input file's name, so it has a .zip extension. --- oioioi/testrun/controllers.py | 9 ++++----- ...09_testrunprogramsubmission_input_is_zip.py | 18 ++++++++++++++++++ oioioi/testrun/models.py | 1 + oioioi/testrun/views.py | 5 ++++- 4 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 oioioi/testrun/migrations/0009_testrunprogramsubmission_input_is_zip.py diff --git a/oioioi/testrun/controllers.py b/oioioi/testrun/controllers.py index 8a53299a9..f8522dc5e 100644 --- a/oioioi/testrun/controllers.py +++ b/oioioi/testrun/controllers.py @@ -1,6 +1,5 @@ import shutil import tempfile -from zipfile import is_zipfile from django import forms from django.conf import settings @@ -209,6 +208,8 @@ def create_testrun( # pylint: disable=maybe-no-member submission.source_file.save(submit_file.name, submit_file) input_file = form_data['input'] + # Same method as in validate_zip + submission.input_is_zip = input_file.name.upper().endswith(".ZIP") submission.input_file.save(input_file.name, input_file) if commit: submission.save() @@ -279,7 +280,7 @@ def render_submission(self, request, submission): context={ 'submission': submission_template_context(request, sbm_testrun), 'supported_extra_args': self.get_supported_extra_args(submission), - 'input_is_zip': is_zipfile(sbm_testrun.input_file), + 'input_is_zip': sbm_testrun.input_is_zip, }, ) @@ -294,9 +295,7 @@ def _render_testrun_report( input_is_zip = False if testrun_report: - input_is_zip = is_zipfile( - testrun_report.submission_report.submission.programsubmission.testrunprogramsubmission.input_file - ) + input_is_zip = testrun_report.submission_report.submission.programsubmission.testrunprogramsubmission.input_is_zip return render_to_string( template, diff --git a/oioioi/testrun/migrations/0009_testrunprogramsubmission_input_is_zip.py b/oioioi/testrun/migrations/0009_testrunprogramsubmission_input_is_zip.py new file mode 100644 index 000000000..84edb9552 --- /dev/null +++ b/oioioi/testrun/migrations/0009_testrunprogramsubmission_input_is_zip.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.16 on 2022-12-20 19:57 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('testrun', '0008_auto_20201214_0012'), + ] + + operations = [ + migrations.AddField( + model_name='testrunprogramsubmission', + name='input_is_zip', + field=models.BooleanField(default=False), + ), + ] diff --git a/oioioi/testrun/models.py b/oioioi/testrun/models.py index cf9d30623..9db0ed0c9 100644 --- a/oioioi/testrun/models.py +++ b/oioioi/testrun/models.py @@ -27,6 +27,7 @@ def make_custom_input_filename(instance, filename): class TestRunProgramSubmission(ProgramSubmission): __test__ = False input_file = FileField(upload_to=make_custom_input_filename) + input_is_zip = models.BooleanField(default=False) def make_custom_output_filename(instance, filename): diff --git a/oioioi/testrun/views.py b/oioioi/testrun/views.py index b6450145e..dc5b28653 100644 --- a/oioioi/testrun/views.py +++ b/oioioi/testrun/views.py @@ -127,7 +127,10 @@ def download_input_file_view(request, submission_id): submission = get_submission_or_error( request, submission_id, TestRunProgramSubmission ) - return stream_file(submission.input_file, name='input.in') + name='input.in' + if submission.input_is_zip: + name+='.zip' + return stream_file(submission.input_file, name=name) @enforce_condition(contest_exists & can_enter_contest) From ae04323a0b871c0349b78eda25f56b5bd780f68a Mon Sep 17 00:00:00 2001 From: A-dead-pixel Date: Sun, 5 Mar 2023 14:00:32 +0100 Subject: [PATCH 2/3] Revert "Fix for issue #123" This reverts commit 30f5fa435bcc3ebb3e0e22ecf01d3b97ac9dd4e0. --- oioioi/testrun/controllers.py | 9 +++++---- ...09_testrunprogramsubmission_input_is_zip.py | 18 ------------------ oioioi/testrun/models.py | 1 - oioioi/testrun/views.py | 5 +---- 4 files changed, 6 insertions(+), 27 deletions(-) delete mode 100644 oioioi/testrun/migrations/0009_testrunprogramsubmission_input_is_zip.py diff --git a/oioioi/testrun/controllers.py b/oioioi/testrun/controllers.py index f8522dc5e..8a53299a9 100644 --- a/oioioi/testrun/controllers.py +++ b/oioioi/testrun/controllers.py @@ -1,5 +1,6 @@ import shutil import tempfile +from zipfile import is_zipfile from django import forms from django.conf import settings @@ -208,8 +209,6 @@ def create_testrun( # pylint: disable=maybe-no-member submission.source_file.save(submit_file.name, submit_file) input_file = form_data['input'] - # Same method as in validate_zip - submission.input_is_zip = input_file.name.upper().endswith(".ZIP") submission.input_file.save(input_file.name, input_file) if commit: submission.save() @@ -280,7 +279,7 @@ def render_submission(self, request, submission): context={ 'submission': submission_template_context(request, sbm_testrun), 'supported_extra_args': self.get_supported_extra_args(submission), - 'input_is_zip': sbm_testrun.input_is_zip, + 'input_is_zip': is_zipfile(sbm_testrun.input_file), }, ) @@ -295,7 +294,9 @@ def _render_testrun_report( input_is_zip = False if testrun_report: - input_is_zip = testrun_report.submission_report.submission.programsubmission.testrunprogramsubmission.input_is_zip + input_is_zip = is_zipfile( + testrun_report.submission_report.submission.programsubmission.testrunprogramsubmission.input_file + ) return render_to_string( template, diff --git a/oioioi/testrun/migrations/0009_testrunprogramsubmission_input_is_zip.py b/oioioi/testrun/migrations/0009_testrunprogramsubmission_input_is_zip.py deleted file mode 100644 index 84edb9552..000000000 --- a/oioioi/testrun/migrations/0009_testrunprogramsubmission_input_is_zip.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.16 on 2022-12-20 19:57 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('testrun', '0008_auto_20201214_0012'), - ] - - operations = [ - migrations.AddField( - model_name='testrunprogramsubmission', - name='input_is_zip', - field=models.BooleanField(default=False), - ), - ] diff --git a/oioioi/testrun/models.py b/oioioi/testrun/models.py index 9db0ed0c9..cf9d30623 100644 --- a/oioioi/testrun/models.py +++ b/oioioi/testrun/models.py @@ -27,7 +27,6 @@ def make_custom_input_filename(instance, filename): class TestRunProgramSubmission(ProgramSubmission): __test__ = False input_file = FileField(upload_to=make_custom_input_filename) - input_is_zip = models.BooleanField(default=False) def make_custom_output_filename(instance, filename): diff --git a/oioioi/testrun/views.py b/oioioi/testrun/views.py index dc5b28653..b6450145e 100644 --- a/oioioi/testrun/views.py +++ b/oioioi/testrun/views.py @@ -127,10 +127,7 @@ def download_input_file_view(request, submission_id): submission = get_submission_or_error( request, submission_id, TestRunProgramSubmission ) - name='input.in' - if submission.input_is_zip: - name+='.zip' - return stream_file(submission.input_file, name=name) + return stream_file(submission.input_file, name='input.in') @enforce_condition(contest_exists & can_enter_contest) From 97c9369b84924de86e9d649fdae659fee285b34d Mon Sep 17 00:00:00 2001 From: A-dead-pixel Date: Sun, 5 Mar 2023 14:01:03 +0100 Subject: [PATCH 3/3] Fix zipfile handling in testruns (issue #123) --- oioioi/testrun/controllers.py | 11 +++++++---- oioioi/testrun/views.py | 7 ++++++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/oioioi/testrun/controllers.py b/oioioi/testrun/controllers.py index 8a53299a9..be4ba4346 100644 --- a/oioioi/testrun/controllers.py +++ b/oioioi/testrun/controllers.py @@ -123,9 +123,12 @@ def adjust_submission_form(self, request, form, problem_instance): if form.kind != 'TESTRUN': return + # We need to check using is_zipfile, as sioworkers do the same. + # Otherwise one could bypass checks and limits for example by + # uploading a zipfile without the '.zip' extension. def validate_file_size(file): if ( - file.name.upper().endswith(".ZIP") + is_zipfile(file) and file.size > self.get_testrun_zipped_input_limit() ): raise ValidationError(_("Zipped input file size limit exceeded.")) @@ -133,7 +136,7 @@ def validate_file_size(file): raise ValidationError(_("Input file size limit exceeded.")) def validate_zip(file): - if file.name.upper().endswith(".ZIP"): + if is_zipfile(file): archive = Archive(file, '.zip') if len(archive.filenames()) != 1: raise ValidationError(_("Archive should have only 1 file inside.")) @@ -279,7 +282,7 @@ def render_submission(self, request, submission): context={ 'submission': submission_template_context(request, sbm_testrun), 'supported_extra_args': self.get_supported_extra_args(submission), - 'input_is_zip': is_zipfile(sbm_testrun.input_file), + 'input_is_zip': is_zipfile(sbm_testrun.input_file.read_using_cache()), }, ) @@ -295,7 +298,7 @@ def _render_testrun_report( input_is_zip = False if testrun_report: input_is_zip = is_zipfile( - testrun_report.submission_report.submission.programsubmission.testrunprogramsubmission.input_file + testrun_report.submission_report.submission.programsubmission.testrunprogramsubmission.input_file.read_using_cache() ) return render_to_string( diff --git a/oioioi/testrun/views.py b/oioioi/testrun/views.py index b6450145e..6675a6998 100644 --- a/oioioi/testrun/views.py +++ b/oioioi/testrun/views.py @@ -1,3 +1,5 @@ +from zipfile import is_zipfile + from django.shortcuts import get_object_or_404, redirect from django.template.response import TemplateResponse from django.urls import reverse @@ -127,7 +129,10 @@ def download_input_file_view(request, submission_id): submission = get_submission_or_error( request, submission_id, TestRunProgramSubmission ) - return stream_file(submission.input_file, name='input.in') + filename = 'input.in' + if is_zipfile(submission.input_file.read_using_cache()): + filename = 'input.zip' + return stream_file(submission.input_file, name=filename) @enforce_condition(contest_exists & can_enter_contest)