From a7b187bbb48db3492278792e5d6e59c1179c6815 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Mon, 9 Nov 2026 17:00:33 +0530 Subject: [PATCH] Serialize ints below the 4-byte range through the long path _save_integral only checked the upper bound, so anything below -2**31 reached struct.pack('!i') and raised a bare struct.error while the same magnitude positive value took the LONGINT path. Check both bounds, and have _write_int4 raise DumpError for either side. --- src/execnet/gateway_base.py | 5 +++-- testing/test_basics.py | 4 +++- testing/test_serializer.py | 9 +++++++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/execnet/gateway_base.py b/src/execnet/gateway_base.py index 5048c45e..dc6d611f 100644 --- a/src/execnet/gateway_base.py +++ b/src/execnet/gateway_base.py @@ -1337,6 +1337,7 @@ def bchr(n: int) -> bytes: DUMPFORMAT_VERSION = bchr(2) FOUR_BYTE_INT_MAX = 2147483647 +FOUR_BYTE_INT_MIN = -2147483648 FLOAT_FORMAT = "!d" FLOAT_FORMAT_SIZE = struct.calcsize(FLOAT_FORMAT) @@ -1693,7 +1694,7 @@ def _write_byte_sequence(self, bytes_: bytes) -> None: self._write(bytes_) def _save_integral(self, i: int, short_op: bytes, long_op: bytes) -> None: - if i <= FOUR_BYTE_INT_MAX: + if FOUR_BYTE_INT_MIN <= i <= FOUR_BYTE_INT_MAX: self._write(short_op) self._write_int4(i) else: @@ -1717,7 +1718,7 @@ def save_complex(self, cpx: complex) -> None: def _write_int4( self, i: int, error: str = "int must be less than %i" % (FOUR_BYTE_INT_MAX,) ) -> None: - if i > FOUR_BYTE_INT_MAX: + if not FOUR_BYTE_INT_MIN <= i <= FOUR_BYTE_INT_MAX: raise DumpError(error) self._write(struct.pack("!i", i)) diff --git a/testing/test_basics.py b/testing/test_basics.py index 1756ec34..4cb20c89 100644 --- a/testing/test_basics.py +++ b/testing/test_basics.py @@ -29,7 +29,9 @@ ) -@pytest.mark.parametrize("val", ["123", 42, [1, 2, 3], ["23", 25]]) +@pytest.mark.parametrize( + "val", ["123", 42, [1, 2, 3], ["23", 25], 2**31, -(2**31) - 1, 10**30, -(10**30)] +) class TestSerializeAPI: def test_serializer_api(self, val: object) -> None: dumped = execnet.dumps(val) diff --git a/testing/test_serializer.py b/testing/test_serializer.py index 06a84cd2..64b59425 100644 --- a/testing/test_serializer.py +++ b/testing/test_serializer.py @@ -125,6 +125,15 @@ def test_long(load, dump) -> None: assert v == really_big +def test_negative_long(load, dump) -> None: + # anything below the 4-byte range must take the long path, like big positives do + really_small = "-9223372036854775807324234" + p = dump(really_small) + tp, v = load(p) + assert tp == "int" + assert v == really_small + + def test_bytes(dump, load) -> None: p = dump("b'hi'") tp, v = load(p)