Skip to content

Commit 4254f29

Browse files
methaneclaude
andcommitted
Reject ext32 length 0xffffffff in the C unpacker
The trail length of an ext value includes the typecode byte, so 0xffffffff + 1 wrapped to zero in 32-bit arithmetic. Unpacker.skip() then treated the 5-byte ext32 header as a complete object and parsed the remaining bytes as the next object. unpack() was already rejected by the max_ext_len check, but with a confusing "0 exceeds" message. Raise ValueError before adding the typecode byte. Reported by Oz Kaiser (@tatikoma). Co-Authored-By: Claude Opus 5.5 <[email protected]>
1 parent c14af4b commit 4254f29

2 files changed

Lines changed: 18 additions & 4 deletions

File tree

‎msgpack/unpack_template.h‎

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -232,10 +232,15 @@ static inline int unpack_execute(bool construct, unpack_context* ctx, const char
232232
again_fixed_trail_if_zero(ACS_EXT_VALUE,
233233
_msgpack_load16(uint16_t,n)+1,
234234
_ext_zero);
235-
case CS_EXT_32:
236-
again_fixed_trail_if_zero(ACS_EXT_VALUE,
237-
_msgpack_load32(uint32_t,n)+1,
238-
_ext_zero);
235+
case CS_EXT_32: {
236+
uint32_t size = _msgpack_load32(uint32_t,n);
237+
// trail includes the typecode, so size+1 must not wrap around.
238+
if (size == UINT32_MAX) {
239+
PyErr_Format(PyExc_ValueError, "%u exceeds max ext length", size);
240+
goto _failed;
241+
}
242+
again_fixed_trail_if_zero(ACS_EXT_VALUE, size+1, _ext_zero);
243+
}
239244
case CS_FLOAT: {
240245
double f;
241246
#if PY_VERSION_HEX >= 0x030B00A7

‎test/test_limits.py‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,15 @@ def test_max_ext_len():
191191
unpacker.unpack()
192192

193193

194+
@pytest.mark.parametrize("method", ["unpack", "skip"])
195+
def test_ext32_max_length(method):
196+
# ext32 with length 0xffffffff followed by bytes that look like another object.
197+
unpacker = Unpacker()
198+
unpacker.feed(b"\xc9\xff\xff\xff\xff" + packb({"a": 1}))
199+
with pytest.raises(UnpackValueError):
200+
getattr(unpacker, method)()
201+
202+
194203
# PyPy fails following tests because of constant folding?
195204
# https://bugs.pypy.org/issue1721
196205
# @pytest.mark.skipif(True, reason="Requires very large memory.")

0 commit comments

Comments
 (0)