Skip to content

Commit d134180

Browse files
authored
unpacker: fix silent datetime truncation with datetime=3 (#701)
1 parent f1a1702 commit d134180

2 files changed

Lines changed: 14 additions & 1 deletion

File tree

msgpack/unpack.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ static int unpack_timestamp(const char* buf, unsigned int buflen, msgpack_timest
283283
ts->tv_sec = _msgpack_load64(int64_t, buf + 4);
284284
return 0;
285285
default:
286+
PyErr_Format(PyExc_ValueError, "invalid timestamp data (length %u)", buflen);
286287
return -1;
287288
}
288289
}
@@ -336,12 +337,18 @@ static int unpack_callback_ext(unpack_user* u, const char* base, const char* pos
336337
else if (u->timestamp == 3) { // datetime
337338
// Calculate datetime using epoch + delta
338339
// due to limitations PyDateTime_FromTimestamp on Windows with negative timestamps
340+
int64_t days = ts.tv_sec / (24*3600);
341+
if (days < INT_MIN || days > INT_MAX) {
342+
PyErr_Format(PyExc_OverflowError,
343+
"days=%lld; too large to convert to C int", days);
344+
return -1;
345+
}
339346
PyObject *epoch = PyDateTimeAPI->DateTime_FromDateAndTime(1970, 1, 1, 0, 0, 0, 0, u->utc, PyDateTimeAPI->DateTimeType);
340347
if (epoch == NULL) {
341348
return -1;
342349
}
343350

344-
PyObject* d = PyDelta_FromDSU(ts.tv_sec/(24*3600), ts.tv_sec%(24*3600), ts.tv_nsec / 1000);
351+
PyObject* d = PyDelta_FromDSU((int)days, ts.tv_sec%(24*3600), ts.tv_nsec / 1000);
345352
if (d == NULL) {
346353
Py_DECREF(epoch);
347354
return -1;

test/test_timestamp.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,3 +176,9 @@ def test_pack_datetime_without_tzinfo():
176176
packed = msgpack.packb(dt, datetime=True)
177177
unpacked = msgpack.unpackb(packed, timestamp=3)
178178
assert unpacked == dt
179+
180+
181+
def test_too_large_timestamp():
182+
# When timestamp64 is too large, conversion to datetime fails due to int64 -> int32 conversion.
183+
# https://github.com/msgpack/msgpack-python/issues/696
184+
print(msgpack.unpackb(b"\xd7\xff" + b"\x00" * 8, timestamp=3))

0 commit comments

Comments
 (0)