From 4516a96db487c004c6e547140372f90c428b79b8 Mon Sep 17 00:00:00 2001 From: Paul Meyer <49727155+katexochen@users.noreply.github.com> Date: Sat, 31 Aug 2024 13:31:24 +0200 Subject: [PATCH] treewide: remove some unreferenced patches Signed-off-by: Paul Meyer <49727155+katexochen@users.noreply.github.com> --- .../patches/nyxt-remove-build-operation.patch | 12 - .../onnx/1.15.0-CVE-2024-27318.patch | 360 ------------------ ...ased-abs-tolerance-for-wilcoxon-test.patch | 25 -- .../0002-Update-test_posthocs.py.patch | 34 -- .../sopel/python311-support.patch | 96 ----- .../curl/8.7.1-compression-fix.patch | 168 -------- 6 files changed, 695 deletions(-) delete mode 100644 pkgs/development/lisp-modules/patches/nyxt-remove-build-operation.patch delete mode 100644 pkgs/development/python-modules/onnx/1.15.0-CVE-2024-27318.patch delete mode 100644 pkgs/development/python-modules/scikit-posthocs/0001-increased-abs-tolerance-for-wilcoxon-test.patch delete mode 100644 pkgs/development/python-modules/scikit-posthocs/0002-Update-test_posthocs.py.patch delete mode 100644 pkgs/development/python-modules/sopel/python311-support.patch delete mode 100644 pkgs/tools/networking/curl/8.7.1-compression-fix.patch diff --git a/pkgs/development/lisp-modules/patches/nyxt-remove-build-operation.patch b/pkgs/development/lisp-modules/patches/nyxt-remove-build-operation.patch deleted file mode 100644 index e050ce10b487..000000000000 --- a/pkgs/development/lisp-modules/patches/nyxt-remove-build-operation.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/nyxt.asd b/nyxt.asd -index ea2630ce..fdf837e4 100644 ---- a/nyxt.asd -+++ b/nyxt.asd -@@ -480,7 +480,6 @@ The renderer is configured from NYXT_RENDERER or `*nyxt-renderer*'.")) - :defsystem-depends-on ("nasdf") - :class :nasdf-system - :depends-on (nyxt/gi-gtk) -- :build-operation "program-op" - :build-pathname "nyxt" - :entry-point "nyxt:entry-point") - diff --git a/pkgs/development/python-modules/onnx/1.15.0-CVE-2024-27318.patch b/pkgs/development/python-modules/onnx/1.15.0-CVE-2024-27318.patch deleted file mode 100644 index 3b95d1fc588c..000000000000 --- a/pkgs/development/python-modules/onnx/1.15.0-CVE-2024-27318.patch +++ /dev/null @@ -1,360 +0,0 @@ -Based on upstream 66b7fb630903fdcf3e83b6b6d56d82e904264a20, adjusted to -apply to 1.15.0 & avoid implicit inclusion of changes from other -intermediate commits - -diff --git a/onnx/checker.cc b/onnx/checker.cc -index fac56f56..c9fda9b2 100644 ---- a/onnx/checker.cc -+++ b/onnx/checker.cc -@@ -13,7 +13,6 @@ - #include <vector> - - #include "onnx/common/file_utils.h" --#include "onnx/common/path.h" - #include "onnx/defs/schema.h" - #include "onnx/defs/tensor_proto_util.h" - #include "onnx/proto_utils.h" -@@ -135,85 +134,7 @@ void check_tensor(const TensorProto& tensor, const CheckerContext& ctx) { - for (const StringStringEntryProto& entry : tensor.external_data()) { - if (entry.has_key() && entry.has_value() && entry.key() == "location") { - has_location = true; --#ifdef _WIN32 -- auto file_path = std::filesystem::path(utf8str_to_wstring(entry.value())); -- if (file_path.is_absolute()) { -- fail_check( -- "Location of external TensorProto ( tensor name: ", -- tensor.name(), -- ") should be a relative path, but it is an absolute path: ", -- entry.value()); -- } -- auto relative_path = file_path.lexically_normal().make_preferred().wstring(); -- // Check that normalized relative path contains ".." on Windows. -- if (relative_path.find(L"..", 0) != std::string::npos) { -- fail_check( -- "Data of TensorProto ( tensor name: ", -- tensor.name(), -- ") should be file inside the ", -- ctx.get_model_dir(), -- ", but the '", -- entry.value(), -- "' points outside the directory"); -- } -- std::wstring data_path = path_join(utf8str_to_wstring(ctx.get_model_dir()), relative_path); -- struct _stat64 buff; -- if (_wstat64(data_path.c_str(), &buff) != 0) { -- fail_check( -- "Data of TensorProto ( tensor name: ", -- tensor.name(), -- ") should be stored in ", -- entry.value(), -- ", but it doesn't exist or is not accessible."); -- } --#else // POSIX -- if (entry.value().empty()) { -- fail_check("Location of external TensorProto ( tensor name: ", tensor.name(), ") should not be empty."); -- } else if (entry.value()[0] == '/') { -- fail_check( -- "Location of external TensorProto ( tensor name: ", -- tensor.name(), -- ") should be a relative path, but it is an absolute path: ", -- entry.value()); -- } -- std::string relative_path = clean_relative_path(entry.value()); -- // Check that normalized relative path contains ".." on POSIX -- if (relative_path.find("..", 0) != std::string::npos) { -- fail_check( -- "Data of TensorProto ( tensor name: ", -- tensor.name(), -- ") should be file inside the ", -- ctx.get_model_dir(), -- ", but the '", -- entry.value(), -- "' points outside the directory"); -- } -- std::string data_path = path_join(ctx.get_model_dir(), relative_path); -- // use stat64 to check whether the file exists --#if defined(__APPLE__) || defined(__wasm__) || !defined(__GLIBC__) -- struct stat buffer; // APPLE, wasm and non-glic stdlibs do not have stat64 -- if (stat((data_path).c_str(), &buffer) != 0) { --#else -- struct stat64 buffer; // All POSIX under glibc except APPLE and wasm have stat64 -- if (stat64((data_path).c_str(), &buffer) != 0) { --#endif -- fail_check( -- "Data of TensorProto ( tensor name: ", -- tensor.name(), -- ") should be stored in ", -- data_path, -- ", but it doesn't exist or is not accessible."); -- } -- // Do not allow symlinks or directories. -- if (!S_ISREG(buffer.st_mode)) { -- fail_check( -- "Data of TensorProto ( tensor name: ", -- tensor.name(), -- ") should be stored in ", -- data_path, -- ", but it is not regular file."); -- } --#endif -+ resolve_external_data_location(ctx.get_model_dir(), entry.value(), tensor.name()); - } - } - if (!has_location) { -@@ -1054,6 +975,93 @@ void check_model(const ModelProto& model, bool full_check, bool skip_opset_compa - } - } - -+std::string resolve_external_data_location( -+ const std::string& base_dir, -+ const std::string& location, -+ const std::string& tensor_name) { -+#ifdef _WIN32 -+ auto file_path = std::filesystem::path(utf8str_to_wstring(location)); -+ if (file_path.is_absolute()) { -+ fail_check( -+ "Location of external TensorProto ( tensor name: ", -+ tensor_name, -+ ") should be a relative path, but it is an absolute path: ", -+ location); -+ } -+ auto relative_path = file_path.lexically_normal().make_preferred().wstring(); -+ // Check that normalized relative path contains ".." on Windows. -+ if (relative_path.find(L"..", 0) != std::string::npos) { -+ fail_check( -+ "Data of TensorProto ( tensor name: ", -+ tensor_name, -+ ") should be file inside the ", -+ base_dir, -+ ", but the '", -+ location, -+ "' points outside the directory"); -+ } -+ std::wstring data_path = path_join(utf8str_to_wstring(base_dir), relative_path); -+ struct _stat64 buff; -+ if (_wstat64(data_path.c_str(), &buff) != 0) { -+ fail_check( -+ "Data of TensorProto ( tensor name: ", -+ tensor_name, -+ ") should be stored in ", -+ location, -+ ", but it doesn't exist or is not accessible."); -+ } -+ return wstring_to_utf8str(data_path); -+#else // POSIX -+ if (location.empty()) { -+ fail_check("Location of external TensorProto ( tensor name: ", tensor_name, ") should not be empty."); -+ } else if (location[0] == '/') { -+ fail_check( -+ "Location of external TensorProto ( tensor name: ", -+ tensor_name, -+ ") should be a relative path, but it is an absolute path: ", -+ location); -+ } -+ std::string relative_path = clean_relative_path(location); -+ // Check that normalized relative path contains ".." on POSIX -+ if (relative_path.find("..", 0) != std::string::npos) { -+ fail_check( -+ "Data of TensorProto ( tensor name: ", -+ tensor_name, -+ ") should be file inside the ", -+ base_dir, -+ ", but the '", -+ location, -+ "' points outside the directory"); -+ } -+ std::string data_path = path_join(base_dir, relative_path); -+ // use stat64 to check whether the file exists -+#if defined(__APPLE__) || defined(__wasm__) || !defined(__GLIBC__) -+ struct stat buffer; // APPLE, wasm and non-glic stdlibs do not have stat64 -+ if (stat((data_path).c_str(), &buffer) != 0) { -+#else -+ struct stat64 buffer; // All POSIX under glibc except APPLE and wasm have stat64 -+ if (stat64((data_path).c_str(), &buffer) != 0) { -+#endif -+ fail_check( -+ "Data of TensorProto ( tensor name: ", -+ tensor_name, -+ ") should be stored in ", -+ data_path, -+ ", but it doesn't exist or is not accessible."); -+ } -+ // Do not allow symlinks or directories. -+ if (!S_ISREG(buffer.st_mode)) { -+ fail_check( -+ "Data of TensorProto ( tensor name: ", -+ tensor_name, -+ ") should be stored in ", -+ data_path, -+ ", but it is not regular file."); -+ } -+ return data_path; -+#endif -+} -+ - std::set<std::string> experimental_ops = { - "ATen", - "Affine", -diff --git a/onnx/checker.h b/onnx/checker.h -index 6796acab..83012213 100644 ---- a/onnx/checker.h -+++ b/onnx/checker.h -@@ -160,7 +160,10 @@ void check_model_local_functions( - - void check_model(const ModelProto& model, bool full_check = false, bool skip_opset_compatibility_check = false); - void check_model(const std::string& model_path, bool full_check = false, bool skip_opset_compatibility_check = false); -- -+std::string resolve_external_data_location( -+ const std::string& base_dir, -+ const std::string& location, -+ const std::string& tensor_name); - bool check_is_experimental_op(const NodeProto& node); - - } // namespace checker -diff --git a/onnx/common/path.h b/onnx/common/path.h -index 6eaf5e67..09212747 100644 ---- a/onnx/common/path.h -+++ b/onnx/common/path.h -@@ -31,11 +31,22 @@ inline std::wstring utf8str_to_wstring(const std::string& utf8str) { - if (utf8str.size() > INT_MAX) { - fail_check("utf8str_to_wstring: string is too long for converting to wstring."); - } -- int size_required = MultiByteToWideChar(CP_UTF8, 0, utf8str.c_str(), (int)utf8str.size(), NULL, 0); -+ int size_required = MultiByteToWideChar(CP_UTF8, 0, utf8str.c_str(), static_cast<int>(utf8str.size()), NULL, 0); - std::wstring ws_str(size_required, 0); -- MultiByteToWideChar(CP_UTF8, 0, utf8str.c_str(), (int)utf8str.size(), &ws_str[0], size_required); -+ MultiByteToWideChar(CP_UTF8, 0, utf8str.c_str(), static_cast<int>(utf8str.size()), &ws_str[0], size_required); - return ws_str; - } -+inline std::string wstring_to_utf8str(const std::wstring& ws_str) { -+ if (ws_str.size() > INT_MAX) { -+ fail_check("wstring_to_utf8str: string is too long for converting to UTF-8."); -+ } -+ int size_required = -+ WideCharToMultiByte(CP_UTF8, 0, ws_str.c_str(), static_cast<int>(ws_str.size()), NULL, 0, NULL, NULL); -+ std::string utf8str(size_required, 0); -+ WideCharToMultiByte( -+ CP_UTF8, 0, ws_str.c_str(), static_cast<int>(ws_str.size()), &utf8str[0], size_required, NULL, NULL); -+ return utf8str; -+} - - #else - std::string path_join(const std::string& origin, const std::string& append); -diff --git a/onnx/cpp2py_export.cc b/onnx/cpp2py_export.cc -index bc2594db..83cea68f 100644 ---- a/onnx/cpp2py_export.cc -+++ b/onnx/cpp2py_export.cc -@@ -545,6 +545,8 @@ PYBIND11_MODULE(onnx_cpp2py_export, onnx_cpp2py_export) { - "full_check"_a = false, - "skip_opset_compatibility_check"_a = false); - -+ checker.def("_resolve_external_data_location", &checker::resolve_external_data_location); -+ - // Submodule `version_converter` - auto version_converter = onnx_cpp2py_export.def_submodule("version_converter"); - version_converter.doc() = "VersionConverter submodule"; -diff --git a/onnx/external_data_helper.py b/onnx/external_data_helper.py -index bbc2717f..05c486c6 100644 ---- a/onnx/external_data_helper.py -+++ b/onnx/external_data_helper.py -@@ -8,6 +8,7 @@ import uuid - from itertools import chain - from typing import Callable, Iterable, Optional - -+import onnx.onnx_cpp2py_export.checker as c_checker - from onnx.onnx_pb import AttributeProto, GraphProto, ModelProto, TensorProto - - -@@ -39,9 +40,9 @@ def load_external_data_for_tensor(tensor: TensorProto, base_dir: str) -> None: - base_dir: directory that contains the external data. - """ - info = ExternalDataInfo(tensor) -- file_location = _sanitize_path(info.location) -- external_data_file_path = os.path.join(base_dir, file_location) -- -+ external_data_file_path = c_checker._resolve_external_data_location( # type: ignore[attr-defined] -+ base_dir, info.location, tensor.name -+ ) - with open(external_data_file_path, "rb") as data_file: - if info.offset: - data_file.seek(info.offset) -@@ -259,14 +260,6 @@ def _get_attribute_tensors(onnx_model_proto: ModelProto) -> Iterable[TensorProto - yield from _get_attribute_tensors_from_graph(onnx_model_proto.graph) - - --def _sanitize_path(path: str) -> str: -- """Remove path components which would allow traversing up a directory tree from a base path. -- -- Note: This method is currently very basic and should be expanded. -- """ -- return path.lstrip("/.") -- -- - def _is_valid_filename(filename: str) -> bool: - """Utility to check whether the provided filename is valid.""" - exp = re.compile('^[^<>:;,?"*|/]+$') -diff --git a/onnx/test/test_external_data.py b/onnx/test/test_external_data.py -index 63f6b4ef..bb14d279 100644 ---- a/onnx/test/test_external_data.py -+++ b/onnx/test/test_external_data.py -@@ -3,6 +3,7 @@ - # SPDX-License-Identifier: Apache-2.0 - from __future__ import annotations - -+import itertools - import os - import pathlib - import tempfile -@@ -204,6 +205,52 @@ class TestLoadExternalDataSingleFile(TestLoadExternalDataBase): - attribute_tensor = new_model.graph.node[0].attribute[0].t - np.testing.assert_allclose(to_array(attribute_tensor), self.attribute_value) - -+ @parameterized.parameterized.expand(itertools.product((True, False), (True, False))) -+ def test_save_external_invalid_single_file_data_and_check( -+ self, use_absolute_path: bool, use_model_path: bool -+ ) -> None: -+ model = onnx.load_model(self.model_filename, self.serialization_format) -+ -+ model_dir = os.path.join(self.temp_dir, "save_copy") -+ os.mkdir(model_dir) -+ -+ traversal_external_data_dir = os.path.join( -+ self.temp_dir, "invlid_external_data" -+ ) -+ os.mkdir(traversal_external_data_dir) -+ -+ if use_absolute_path: -+ traversal_external_data_location = os.path.join( -+ traversal_external_data_dir, "tensors.bin" -+ ) -+ else: -+ traversal_external_data_location = "../invlid_external_data/tensors.bin" -+ -+ external_data_dir = os.path.join(self.temp_dir, "external_data") -+ os.mkdir(external_data_dir) -+ new_model_filepath = os.path.join(model_dir, "model.onnx") -+ -+ def convert_model_to_external_data_no_check(model: ModelProto, location: str): -+ for tensor in model.graph.initializer: -+ if tensor.HasField("raw_data"): -+ set_external_data(tensor, location) -+ -+ convert_model_to_external_data_no_check( -+ model, -+ location=traversal_external_data_location, -+ ) -+ -+ onnx.save_model(model, new_model_filepath, self.serialization_format) -+ if use_model_path: -+ with self.assertRaises(onnx.checker.ValidationError): -+ _ = onnx.load_model(new_model_filepath, self.serialization_format) -+ else: -+ onnx_model = onnx.load_model( -+ new_model_filepath, self.serialization_format, load_external_data=False -+ ) -+ with self.assertRaises(onnx.checker.ValidationError): -+ load_external_data_for_model(onnx_model, external_data_dir) -+ - - @parameterized.parameterized_class( - [ diff --git a/pkgs/development/python-modules/scikit-posthocs/0001-increased-abs-tolerance-for-wilcoxon-test.patch b/pkgs/development/python-modules/scikit-posthocs/0001-increased-abs-tolerance-for-wilcoxon-test.patch deleted file mode 100644 index e3fa524e5a4f..000000000000 --- a/pkgs/development/python-modules/scikit-posthocs/0001-increased-abs-tolerance-for-wilcoxon-test.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 02266a00ce0eb6a089e7efe07816da1aa5152fc9 Mon Sep 17 00:00:00 2001 -From: Maksim Terpilovskii <maximtrp@gmail.com> -Date: Sun, 31 Jul 2022 12:25:14 +0300 -Subject: [PATCH] increased abs tolerance for wilcoxon test - ---- - tests/test_posthocs.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/tests/test_posthocs.py b/tests/test_posthocs.py -index 956d808..8cc65e4 100644 ---- a/tests/test_posthocs.py -+++ b/tests/test_posthocs.py -@@ -471,7 +471,7 @@ class TestPosthocs(unittest.TestCase): - [2.857818e-06, 1.230888e-05, 1]]) - - results = sp.posthoc_wilcoxon(self.df.sort_index(), val_col = 'pulse', group_col = 'kind') -- self.assertTrue(np.allclose(results, r_results)) -+ self.assertTrue(np.allclose(results, r_results, atol=1e-4)) - - - def test_posthoc_scheffe(self): --- -2.36.1 - diff --git a/pkgs/development/python-modules/scikit-posthocs/0002-Update-test_posthocs.py.patch b/pkgs/development/python-modules/scikit-posthocs/0002-Update-test_posthocs.py.patch deleted file mode 100644 index fa4d6d3ececf..000000000000 --- a/pkgs/development/python-modules/scikit-posthocs/0002-Update-test_posthocs.py.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 5416ffba3ab01aebab3909400b5a9e847022898e Mon Sep 17 00:00:00 2001 -From: Maksim Terpilovskii <maximtrp@gmail.com> -Date: Thu, 16 Mar 2023 00:20:02 +0300 -Subject: [PATCH] Update test_posthocs.py - ---- - tests/test_posthocs.py | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/tests/test_posthocs.py b/tests/test_posthocs.py -index 8cc65e4..42ca5f3 100644 ---- a/tests/test_posthocs.py -+++ b/tests/test_posthocs.py -@@ -71,7 +71,7 @@ class TestPosthocs(unittest.TestCase): - a = splt.sign_plot(x, flat=True, labels=False) - with self.assertRaises(ValueError): - splt.sign_plot(x.astype(float), flat=True, labels=False) -- self.assertTrue(isinstance(a, ma._subplots.Axes)) -+ self.assertTrue(isinstance(a, ma._axes.Axes)) - - def test_sign_plot_nonflat(self): - -@@ -85,7 +85,7 @@ class TestPosthocs(unittest.TestCase): - with self.assertRaises(ValueError): - splt.sign_plot(x.astype(np.int64), labels=False) - -- self.assertTrue(isinstance(a, ma._subplots.Axes) and isinstance(cbar, mpl.colorbar.ColorbarBase)) -+ self.assertTrue(isinstance(a, ma._axes.Axes) and isinstance(cbar, mpl.colorbar.ColorbarBase)) - - # Outliers tests - def test_outliers_iqr(self): --- -2.36.1 - diff --git a/pkgs/development/python-modules/sopel/python311-support.patch b/pkgs/development/python-modules/sopel/python311-support.patch deleted file mode 100644 index dfa0283409ac..000000000000 --- a/pkgs/development/python-modules/sopel/python311-support.patch +++ /dev/null @@ -1,96 +0,0 @@ -diff --git a/sopel/plugins/handlers.py b/sopel/plugins/handlers.py -index 76902aa0..05f0279d 100644 ---- a/sopel/plugins/handlers.py -+++ b/sopel/plugins/handlers.py -@@ -46,20 +46,15 @@ from __future__ import absolute_import, division, print_function, unicode_litera - - import imp - import importlib -+import importlib.util - import inspect - import itertools - import os -+import sys - - from sopel import loader - from . import exceptions - --try: -- reload = importlib.reload --except AttributeError: -- # py2: no reload function -- # TODO: imp is deprecated, to be removed when py2 support is dropped -- reload = imp.reload -- - - class AbstractPluginHandler(object): - """Base class for plugin handlers. -@@ -301,7 +296,7 @@ class PyModulePlugin(AbstractPluginHandler): - - This method assumes the plugin is already loaded. - """ -- self._module = reload(self._module) -+ self._module = importlib.reload(self._module) - - def is_loaded(self): - return self._module is not None -@@ -402,45 +397,31 @@ class PyFilePlugin(PyModulePlugin): - - if good_file: - name = os.path.basename(filename)[:-3] -- module_type = imp.PY_SOURCE -+ spec = importlib.util.spec_from_file_location( -+ name, -+ filename, -+ ) - elif good_dir: - name = os.path.basename(filename) -- module_type = imp.PKG_DIRECTORY -+ spec = importlib.util.spec_from_file_location( -+ name, -+ os.path.join(filename, '__init__.py'), -+ submodule_search_locations=filename, -+ ) - else: - raise exceptions.PluginError('Invalid Sopel plugin: %s' % filename) - - self.filename = filename - self.path = filename -- self.module_type = module_type -+ self.module_spec = spec - - super(PyFilePlugin, self).__init__(name) - - def _load(self): -- # The current implementation uses `imp.load_module` to perform the -- # load action, which also reloads the module. However, `imp` is -- # deprecated in Python 3, so that might need to be changed when the -- # support for Python 2 is dropped. -- # -- # However, the solution for Python 3 is non-trivial, since the -- # `importlib` built-in module does not have a similar function, -- # therefore requires to dive into its public internals -- # (``importlib.machinery`` and ``importlib.util``). -- # -- # All of that is doable, but represents a lot of work. As long as -- # Python 2 is supported, we can keep it for now. -- # -- # TODO: switch to ``importlib`` when Python2 support is dropped. -- if self.module_type == imp.PY_SOURCE: -- with open(self.path) as mod: -- description = ('.py', 'U', self.module_type) -- mod = imp.load_module(self.name, mod, self.path, description) -- elif self.module_type == imp.PKG_DIRECTORY: -- description = ('', '', self.module_type) -- mod = imp.load_module(self.name, None, self.path, description) -- else: -- raise TypeError('Unsupported module type') -- -- return mod -+ module = importlib.util.module_from_spec(self.module_spec) -+ sys.modules[self.name] = module -+ self.module_spec.loader.exec_module(module) -+ return module - - def get_meta_description(self): - """Retrieve a meta description for the plugin. diff --git a/pkgs/tools/networking/curl/8.7.1-compression-fix.patch b/pkgs/tools/networking/curl/8.7.1-compression-fix.patch deleted file mode 100644 index 53747b54c461..000000000000 --- a/pkgs/tools/networking/curl/8.7.1-compression-fix.patch +++ /dev/null @@ -1,168 +0,0 @@ -From b30d694a027eb771c02a3db0dee0ca03ccab7377 Mon Sep 17 00:00:00 2001 -From: Stefan Eissing <stefan@eissing.org> -Date: Thu, 28 Mar 2024 11:08:15 +0100 -Subject: [PATCH] content_encoding: brotli and others, pass through 0-length - writes - -- curl's transfer handling may write 0-length chunks at the end of the - download with an EOS flag. (HTTP/2 does this commonly) - -- content encoders need to pass-through such a write and not count this - as error in case they are finished decoding - -Fixes #13209 -Fixes #13212 -Closes #13219 ---- - lib/content_encoding.c | 10 +++++----- - tests/http/test_02_download.py | 13 +++++++++++++ - tests/http/testenv/env.py | 7 ++++++- - tests/http/testenv/httpd.py | 20 ++++++++++++++++++++ - 4 files changed, 44 insertions(+), 6 deletions(-) - -diff --git a/lib/content_encoding.c b/lib/content_encoding.c -index c1abf24e8c027c..8e926dd2ecd5ad 100644 ---- a/lib/content_encoding.c -+++ b/lib/content_encoding.c -@@ -300,7 +300,7 @@ static CURLcode deflate_do_write(struct Curl_easy *data, - struct zlib_writer *zp = (struct zlib_writer *) writer; - z_stream *z = &zp->z; /* zlib state structure */ - -- if(!(type & CLIENTWRITE_BODY)) -+ if(!(type & CLIENTWRITE_BODY) || !nbytes) - return Curl_cwriter_write(data, writer->next, type, buf, nbytes); - - /* Set the compressed input when this function is called */ -@@ -457,7 +457,7 @@ static CURLcode gzip_do_write(struct Curl_easy *data, - struct zlib_writer *zp = (struct zlib_writer *) writer; - z_stream *z = &zp->z; /* zlib state structure */ - -- if(!(type & CLIENTWRITE_BODY)) -+ if(!(type & CLIENTWRITE_BODY) || !nbytes) - return Curl_cwriter_write(data, writer->next, type, buf, nbytes); - - if(zp->zlib_init == ZLIB_INIT_GZIP) { -@@ -669,7 +669,7 @@ static CURLcode brotli_do_write(struct Curl_easy *data, - CURLcode result = CURLE_OK; - BrotliDecoderResult r = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT; - -- if(!(type & CLIENTWRITE_BODY)) -+ if(!(type & CLIENTWRITE_BODY) || !nbytes) - return Curl_cwriter_write(data, writer->next, type, buf, nbytes); - - if(!bp->br) -@@ -762,7 +762,7 @@ static CURLcode zstd_do_write(struct Curl_easy *data, - ZSTD_outBuffer out; - size_t errorCode; - -- if(!(type & CLIENTWRITE_BODY)) -+ if(!(type & CLIENTWRITE_BODY) || !nbytes) - return Curl_cwriter_write(data, writer->next, type, buf, nbytes); - - if(!zp->decomp) { -@@ -916,7 +916,7 @@ static CURLcode error_do_write(struct Curl_easy *data, - (void) buf; - (void) nbytes; - -- if(!(type & CLIENTWRITE_BODY)) -+ if(!(type & CLIENTWRITE_BODY) || !nbytes) - return Curl_cwriter_write(data, writer->next, type, buf, nbytes); - - failf(data, "Unrecognized content encoding type. " -diff --git a/tests/http/test_02_download.py b/tests/http/test_02_download.py -index 4db9c9d36e9ed5..395fc862f2f839 100644 ---- a/tests/http/test_02_download.py -+++ b/tests/http/test_02_download.py -@@ -394,6 +394,19 @@ def test_02_27_paused_no_cl(self, env: Env, httpd, nghttpx, repeat): - r = client.run(args=[url]) - r.check_exit_code(0) - -+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3']) -+ def test_02_28_get_compressed(self, env: Env, httpd, nghttpx, repeat, proto): -+ if proto == 'h3' and not env.have_h3(): -+ pytest.skip("h3 not supported") -+ count = 1 -+ urln = f'https://{env.authority_for(env.domain1brotli, proto)}/data-100k?[0-{count-1}]' -+ curl = CurlClient(env=env) -+ r = curl.http_download(urls=[urln], alpn_proto=proto, extra_args=[ -+ '--compressed' -+ ]) -+ r.check_exit_code(code=0) -+ r.check_response(count=count, http_status=200) -+ - def check_downloads(self, client, srcfile: str, count: int, - complete: bool = True): - for i in range(count): -diff --git a/tests/http/testenv/env.py b/tests/http/testenv/env.py -index a207059dcd57c5..13c5d6bd46ee57 100644 ---- a/tests/http/testenv/env.py -+++ b/tests/http/testenv/env.py -@@ -129,10 +129,11 @@ def __init__(self): - self.htdocs_dir = os.path.join(self.gen_dir, 'htdocs') - self.tld = 'http.curl.se' - self.domain1 = f"one.{self.tld}" -+ self.domain1brotli = f"brotli.one.{self.tld}" - self.domain2 = f"two.{self.tld}" - self.proxy_domain = f"proxy.{self.tld}" - self.cert_specs = [ -- CertificateSpec(domains=[self.domain1, 'localhost'], key_type='rsa2048'), -+ CertificateSpec(domains=[self.domain1, self.domain1brotli, 'localhost'], key_type='rsa2048'), - CertificateSpec(domains=[self.domain2], key_type='rsa2048'), - CertificateSpec(domains=[self.proxy_domain, '127.0.0.1'], key_type='rsa2048'), - CertificateSpec(name="clientsX", sub_specs=[ -@@ -376,6 +377,10 @@ def htdocs_dir(self) -> str: - def domain1(self) -> str: - return self.CONFIG.domain1 - -+ @property -+ def domain1brotli(self) -> str: -+ return self.CONFIG.domain1brotli -+ - @property - def domain2(self) -> str: - return self.CONFIG.domain2 -diff --git a/tests/http/testenv/httpd.py b/tests/http/testenv/httpd.py -index c04c22699a62c4..b8615875a9a558 100644 ---- a/tests/http/testenv/httpd.py -+++ b/tests/http/testenv/httpd.py -@@ -50,6 +50,7 @@ class Httpd: - 'alias', 'env', 'filter', 'headers', 'mime', 'setenvif', - 'socache_shmcb', - 'rewrite', 'http2', 'ssl', 'proxy', 'proxy_http', 'proxy_connect', -+ 'brotli', - 'mpm_event', - ] - COMMON_MODULES_DIRS = [ -@@ -203,6 +204,7 @@ def _mkpath(self, path): - - def _write_config(self): - domain1 = self.env.domain1 -+ domain1brotli = self.env.domain1brotli - creds1 = self.env.get_credentials(domain1) - domain2 = self.env.domain2 - creds2 = self.env.get_credentials(domain2) -@@ -285,6 +287,24 @@ def _write_config(self): - f'</VirtualHost>', - f'', - ]) -+ # Alternate to domain1 with BROTLI compression -+ conf.extend([ # https host for domain1, h1 + h2 -+ f'<VirtualHost *:{self.env.https_port}>', -+ f' ServerName {domain1brotli}', -+ f' Protocols h2 http/1.1', -+ f' SSLEngine on', -+ f' SSLCertificateFile {creds1.cert_file}', -+ f' SSLCertificateKeyFile {creds1.pkey_file}', -+ f' DocumentRoot "{self._docs_dir}"', -+ f' SetOutputFilter BROTLI_COMPRESS', -+ ]) -+ conf.extend(self._curltest_conf(domain1)) -+ if domain1 in self._extra_configs: -+ conf.extend(self._extra_configs[domain1]) -+ conf.extend([ -+ f'</VirtualHost>', -+ f'', -+ ]) - conf.extend([ # https host for domain2, no h2 - f'<VirtualHost *:{self.env.https_port}>', - f' ServerName {domain2}',