Version in base suite: 3.26.1-0.2 Base version: python-marshmallow_3.26.1-0.2 Target version: python-marshmallow_3.26.2-0+deb13u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/p/python-marshmallow/python-marshmallow_3.26.1-0.2.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/p/python-marshmallow/python-marshmallow_3.26.2-0+deb13u1.dsc CHANGELOG.rst | 8 ++++++++ debian/changelog | 8 ++++++++ pyproject.toml | 4 ++-- src/marshmallow/error_store.py | 35 +++++++++++++++++++++++------------ src/marshmallow/schema.py | 4 ++-- tests/test_error_store.py | 18 +++++++++++++++++- 6 files changed, 60 insertions(+), 17 deletions(-) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpau6xvk0p/python-marshmallow_3.26.1-0.2.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpau6xvk0p/python-marshmallow_3.26.2-0+deb13u1.dsc: no acceptable signature found diff -Nru python-marshmallow-3.26.1/CHANGELOG.rst python-marshmallow-3.26.2/CHANGELOG.rst --- python-marshmallow-3.26.1/CHANGELOG.rst 2025-02-03 15:31:14.000000000 +0000 +++ python-marshmallow-3.26.2/CHANGELOG.rst 2025-12-22 06:51:52.000000000 +0000 @@ -1,6 +1,14 @@ Changelog --------- +3.26.2 (2025-12-19) +++++++++++++++++++ + +Bug fixes: + +- :cve:`CVE-2025-68480`: Merge error store messages without rebuilding collections. + Thanks 카푸치노 for reporting and :user:`deckar01` for the fix. + 3.26.1 (2025-02-03) ******************* diff -Nru python-marshmallow-3.26.1/debian/changelog python-marshmallow-3.26.2/debian/changelog --- python-marshmallow-3.26.1/debian/changelog 2025-03-26 11:58:32.000000000 +0000 +++ python-marshmallow-3.26.2/debian/changelog 2026-06-28 08:20:03.000000000 +0000 @@ -1,3 +1,11 @@ +python-marshmallow (3.26.2-0+deb13u1) trixie; urgency=medium + + * Non-maintainer upload. + * New upstream release. + - CVE-2025-68480: DoS with Schema.load(many) (Closes: #1123888) + + -- Adrian Bunk Sun, 28 Jun 2026 11:20:03 +0300 + python-marshmallow (3.26.1-0.2) unstable; urgency=medium * Non-maintainer upload. diff -Nru python-marshmallow-3.26.1/pyproject.toml python-marshmallow-3.26.2/pyproject.toml --- python-marshmallow-3.26.1/pyproject.toml 2025-02-03 15:31:14.000000000 +0000 +++ python-marshmallow-3.26.2/pyproject.toml 2025-12-22 06:51:52.000000000 +0000 @@ -1,6 +1,6 @@ [project] name = "marshmallow" -version = "3.26.1" +version = "3.26.2" description = "A lightweight library for converting complex datatypes to and from native Python datatypes." readme = "README.rst" license = { file = "LICENSE" } @@ -121,7 +121,7 @@ [tool.mypy] files = ["src", "tests", "examples"] ignore_missing_imports = true -warn_unreachable = true +warn_unreachable = false warn_unused_ignores = true warn_redundant_casts = true no_implicit_optional = true diff -Nru python-marshmallow-3.26.1/src/marshmallow/error_store.py python-marshmallow-3.26.2/src/marshmallow/error_store.py --- python-marshmallow-3.26.1/src/marshmallow/error_store.py 2025-02-03 15:31:14.000000000 +0000 +++ python-marshmallow-3.26.2/src/marshmallow/error_store.py 2025-12-22 06:51:52.000000000 +0000 @@ -18,6 +18,7 @@ # field error -> store/merge error messages under field name key # schema error -> if string or list, store/merge under _schema key # -> if dict, store/merge with other top-level keys + messages = copy_containers(messages) if field_name != SCHEMA or not isinstance(messages, dict): messages = {field_name: messages} if index is not None: @@ -25,6 +26,14 @@ self.errors = merge_errors(self.errors, messages) +def copy_containers(errors): + if isinstance(errors, list): + return [copy_containers(val) for val in errors] + if isinstance(errors, dict): + return {key: copy_containers(val) for key, val in errors.items()} + return errors + + def merge_errors(errors1, errors2): # noqa: PLR0911 """Deeply merge two error messages. @@ -37,24 +46,26 @@ return errors1 if isinstance(errors1, list): if isinstance(errors2, list): - return errors1 + errors2 + errors1.extend(errors2) + return errors1 if isinstance(errors2, dict): - return dict(errors2, **{SCHEMA: merge_errors(errors1, errors2.get(SCHEMA))}) - return [*errors1, errors2] + errors2[SCHEMA] = merge_errors(errors1, errors2.get(SCHEMA)) + return errors2 + errors1.append(errors2) + return errors1 if isinstance(errors1, dict): - if isinstance(errors2, list): - return dict(errors1, **{SCHEMA: merge_errors(errors1.get(SCHEMA), errors2)}) if isinstance(errors2, dict): - errors = dict(errors1) for key, val in errors2.items(): - if key in errors: - errors[key] = merge_errors(errors[key], val) + if key in errors1: + errors1[key] = merge_errors(errors1[key], val) else: - errors[key] = val - return errors - return dict(errors1, **{SCHEMA: merge_errors(errors1.get(SCHEMA), errors2)}) + errors1[key] = val + return errors1 + errors1[SCHEMA] = merge_errors(errors1.get(SCHEMA), errors2) + return errors1 if isinstance(errors2, list): return [errors1, *errors2] if isinstance(errors2, dict): - return dict(errors2, **{SCHEMA: merge_errors(errors1, errors2.get(SCHEMA))}) + errors2[SCHEMA] = merge_errors(errors1, errors2.get(SCHEMA)) + return errors2 return [errors1, errors2] diff -Nru python-marshmallow-3.26.1/src/marshmallow/schema.py python-marshmallow-3.26.2/src/marshmallow/schema.py --- python-marshmallow-3.26.1/src/marshmallow/schema.py 2025-02-03 15:31:14.000000000 +0000 +++ python-marshmallow-3.26.2/src/marshmallow/schema.py 2025-12-22 06:51:52.000000000 +0000 @@ -374,7 +374,7 @@ class MySchema2(Schema): # Type checkers will check attributes - class Meta(Schema.Opts): + class Meta(Schema.Meta): additional = True # Incompatible types in assignment .. versionremoved:: 3.0.0b7 Remove ``strict``. @@ -1139,7 +1139,7 @@ msg = ( f'Field for "{field_name}" must be declared as a ' "Field instance, not a class. " - f'Did you mean "fields.{field_obj.__name__}()"?' # type: ignore[attr-defined] + f'Did you mean "fields.{field_obj.__name__}()"?' ) raise TypeError(msg) from error raise diff -Nru python-marshmallow-3.26.1/tests/test_error_store.py python-marshmallow-3.26.2/tests/test_error_store.py --- python-marshmallow-3.26.1/tests/test_error_store.py 2025-02-03 15:31:14.000000000 +0000 +++ python-marshmallow-3.26.2/tests/test_error_store.py 2025-12-22 06:51:52.000000000 +0000 @@ -1,7 +1,7 @@ from typing import NamedTuple from marshmallow import missing -from marshmallow.error_store import merge_errors +from marshmallow.error_store import ErrorStore, merge_errors def test_missing_is_falsy(): @@ -149,3 +149,19 @@ assert merge_errors( {"field1": {"field2": "error1"}}, {"field1": {"field2": "error2"}} ) == {"field1": {"field2": ["error1", "error2"]}} + + def test_list_not_changed(self): + store = ErrorStore() + message = ["foo"] + store.store_error(message) + store.store_error(message) + assert message == ["foo"] + assert store.errors == {"_schema": ["foo", "foo"]} + + def test_dict_not_changed(self): + store = ErrorStore() + message = {"foo": ["bar"]} + store.store_error(message) + store.store_error(message) + assert message == {"foo": ["bar"]} + assert store.errors == {"foo": ["bar", "bar"]}