From 018307f668d5758b5ea9e3b6e08bb4eaf51141f0 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Fri, 19 Jun 2026 18:49:41 +0900 Subject: [PATCH 1/2] unpacker: fix silent datetime truncation with datetime=3 --- msgpack/unpack.h | 9 ++++++++- test/test_timestamp.py | 5 +++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/msgpack/unpack.h b/msgpack/unpack.h index 0f9ffc05..55cfdab9 100644 --- a/msgpack/unpack.h +++ b/msgpack/unpack.h @@ -283,6 +283,7 @@ static int unpack_timestamp(const char* buf, unsigned int buflen, msgpack_timest ts->tv_sec = _msgpack_load64(int64_t, buf + 4); return 0; default: + PyErr_Format(PyExc_ValueError, "invalid timestamp data (length %u)", buflen); return -1; } } @@ -336,12 +337,18 @@ static int unpack_callback_ext(unpack_user* u, const char* base, const char* pos else if (u->timestamp == 3) { // datetime // Calculate datetime using epoch + delta // due to limitations PyDateTime_FromTimestamp on Windows with negative timestamps + int64_t days = ts.tv_sec / (24*3600); + if (days < INT_MIN || days > INT_MAX) { + PyErr_Format(PyExc_OverflowError, + "days=%lld; too large to convert to C int", days); + return -1; + } PyObject *epoch = PyDateTimeAPI->DateTime_FromDateAndTime(1970, 1, 1, 0, 0, 0, 0, u->utc, PyDateTimeAPI->DateTimeType); if (epoch == NULL) { return -1; } - PyObject* d = PyDelta_FromDSU(ts.tv_sec/(24*3600), ts.tv_sec%(24*3600), ts.tv_nsec / 1000); + PyObject* d = PyDelta_FromDSU((int)days, ts.tv_sec%(24*3600), ts.tv_nsec / 1000); if (d == NULL) { Py_DECREF(epoch); return -1; diff --git a/test/test_timestamp.py b/test/test_timestamp.py index 6dfe3689..55a0da04 100644 --- a/test/test_timestamp.py +++ b/test/test_timestamp.py @@ -176,3 +176,8 @@ def test_pack_datetime_without_tzinfo(): packed = msgpack.packb(dt, datetime=True) unpacked = msgpack.unpackb(packed, timestamp=3) assert unpacked == dt + + +def test_too_large_timestamp(): + # timestamp64 format が大きすぎるとき、int64 ->int32 変換でdatetime型への変換が失敗する。 + print(msgpack.unpackb(b"\xd7\xff" + b"\x00" * 8, timestamp=3)) From 58bbd08847093c5332b5bb54b425d211d2c1b863 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Fri, 19 Jun 2026 18:51:25 +0900 Subject: [PATCH 2/2] fix comment --- test/test_timestamp.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/test_timestamp.py b/test/test_timestamp.py index 55a0da04..7c8e3e83 100644 --- a/test/test_timestamp.py +++ b/test/test_timestamp.py @@ -179,5 +179,6 @@ def test_pack_datetime_without_tzinfo(): def test_too_large_timestamp(): - # timestamp64 format が大きすぎるとき、int64 ->int32 変換でdatetime型への変換が失敗する。 + # When timestamp64 is too large, conversion to datetime fails due to int64 -> int32 conversion. + # https://github.com/msgpack/msgpack-python/issues/696 print(msgpack.unpackb(b"\xd7\xff" + b"\x00" * 8, timestamp=3))