From cd8137093ac0abcfa9acc9d9c2ad6abeeee8ad30 Mon Sep 17 00:00:00 2001 From: Thomas Kowalski Date: Tue, 12 May 2026 06:59:40 +0200 Subject: [PATCH] fix: enforce `strict_map_key` with `object_pairs_hook` (#673) This PR makes it so that `self._strict_map_key` is enforced even when using `_object_pairs_hook` which didn't use to be the case. --- msgpack/fallback.py | 12 +++++++++--- test/test_except.py | 14 ++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/msgpack/fallback.py b/msgpack/fallback.py index b02e47c..d71bbfc 100644 --- a/msgpack/fallback.py +++ b/msgpack/fallback.py @@ -518,9 +518,15 @@ class Unpacker: self._unpack(EX_SKIP) return if self._object_pairs_hook is not None: - ret = self._object_pairs_hook( - (self._unpack(EX_CONSTRUCT), self._unpack(EX_CONSTRUCT)) for _ in range(n) - ) + + def _gen(): + for _ in range(n): + key = self._unpack(EX_CONSTRUCT) + if self._strict_map_key and type(key) not in (str, bytes): + raise ValueError("%s is not allowed for map key" % str(type(key))) + yield key, self._unpack(EX_CONSTRUCT) + + ret = self._object_pairs_hook(_gen()) else: ret = {} for _ in range(n): diff --git a/test/test_except.py b/test/test_except.py index c56a6a3..be8ca4c 100644 --- a/test/test_except.py +++ b/test/test_except.py @@ -89,3 +89,17 @@ def test_strict_map_key(): packed = packb(invalid, use_bin_type=True) with raises(ValueError): unpackb(packed, raw=False, strict_map_key=True) + + +def test_strict_map_key_with_object_pairs_hook(): + # strict_map_key should be enforced even when object_pairs_hook is set + invalid = {42: "value"} + packed = packb(invalid, use_bin_type=True) + with raises(ValueError): + unpackb(packed, raw=False, strict_map_key=True, object_pairs_hook=list) + + # valid keys (str/bytes) should still work with object_pairs_hook + valid = {"key": "value"} + packed = packb(valid, use_bin_type=True) + result = unpackb(packed, raw=False, strict_map_key=True, object_pairs_hook=list) + assert result == [("key", "value")]