From 2ef9da05f75b9cb492669dc5b34c78e62073ac84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=B2=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=81?= Date: Fri, 20 Nov 2020 18:15:51 +0300 Subject: [PATCH] Added check if an input file is a binary while joining templates. fixed #16 --- calculate/templates/template_processor.py | 8 +++++-- tests/templates/test_template_executor.py | 21 ++++++++++++++++++ .../append_join_file_testfiles/logo.png | Bin 0 -> 11587 bytes 3 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 tests/templates/testfiles/test_executor_root/etc.backup/append_join_file_testfiles/logo.png diff --git a/calculate/templates/template_processor.py b/calculate/templates/template_processor.py index e8289ce..16b3bc0 100644 --- a/calculate/templates/template_processor.py +++ b/calculate/templates/template_processor.py @@ -1028,8 +1028,12 @@ class TemplateExecutor: or os.path.exists(input_path)): # Если входной файл просто не из архива, или из архива # и при этом существует -- используем его - with open(input_path, 'r') as input_file: - input_text = input_file.read() + try: + with open(input_path, 'r') as input_file: + input_text = input_file.read() + except UnicodeDecodeError: + raise TemplateExecutorError( + "can not join binary files.") else: # В противном случае используем пустой файл. # TODO Подумать. diff --git a/tests/templates/test_template_executor.py b/tests/templates/test_template_executor.py index c4facf3..dc82da4 100644 --- a/tests/templates/test_template_executor.py +++ b/tests/templates/test_template_executor.py @@ -3042,6 +3042,27 @@ AttributeError: module 'os' has no attribute 'suspicious_attribute' out_text = out_file.read() assert out_text == expected_output + def test_error_while_using_not_text_file_as_input_file_for_append_join(self): + target_path = join_paths(CHROOT_PATH, + '/etc/append_join_file_testfiles/file_19') + source_path = join_paths(CHROOT_PATH, + '/etc/append_join_file_testfiles/logo.png') + + parameters_object = ParametersContainer({'package': test_package_name, + 'append': 'join', + 'source': source_path, + 'format': 'raw'}) + + template_wrapper = TemplateWrapper( + target_path, + parameters_object, FILE, + '/path/to/template', + template_text='', + chroot_path=CHROOT_PATH, + config_archive_path=CONFIG_ARCHIVE_PATH) + with pytest.raises(TemplateExecutorError): + template_executor._append_join_file(template_wrapper) + def test_to_remove_changed_testfiles(self): shutil.rmtree(os.path.join(CHROOT_PATH, 'etc')) shutil.rmtree(os.path.join(CHROOT_PATH, 'unprotected')) diff --git a/tests/templates/testfiles/test_executor_root/etc.backup/append_join_file_testfiles/logo.png b/tests/templates/testfiles/test_executor_root/etc.backup/append_join_file_testfiles/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c1de580da55e8e3b04d3ba4c753d6de77e42fe56 GIT binary patch literal 11587 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 literal 0 HcmV?d00001