diff --git a/msgpack/fallback.py b/msgpack/fallback.py index b02e47cf..d71bbfc7 100644 --- a/msgpack/fallback.py +++ b/msgpack/fallback.py @@ -518,9 +518,15 @@ def _unpack(self, execute=EX_CONSTRUCT): 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 c56a6a30..be8ca4cf 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")]