From 787333f8b0cab8166af3fa6a3425308e682ee474 Mon Sep 17 00:00:00 2001 From: Logan Gunthorpe Date: Tue, 15 Aug 2023 17:53:52 -0600 Subject: [PATCH] Handle partial message in ReadDeviceInformationResponse When a partial message is received for a ReadDeviceInformationResponse, an exception occurs when calculating the frame size: ERROR:asyncio:Exception in callback SerialTransport._read_ready() handle: Traceback (most recent call last): File "/usr/lib/python3.9/asyncio/events.py", line 80, in _run self._context.run(self._callback, *self._args) File "pymodbus/transport/transport_serial.py", line 109, in _read_ready self._protocol.data_received(data) File "pymodbus/transport/transport.py", line 307, in data_received self.datagram_received(data, None) File "pymodbus/transport/transport.py", line 328, in datagram_received cut = self.callback_data(self.recv_buffer, addr=addr) File "pymodbus/client/base.py", line 218, in callback_data self.framer.processIncomingPacket(data, self._handle_response, slave=0) File "pymodbus/framer/base.py", line 137, in processIncomingPacket self.frameProcessIncomingPacket(single, callback, slave, **kwargs) File "pymodbus/framer/rtu_framer.py", line 213, in frameProcessIncomingPacket if not self.isFrameReady(): File "pymodbus/framer/rtu_framer.py", line 134, in isFrameReady size = self.populateHeader() File "pymodbus/framer/rtu_framer.py", line 152, in populateHeader size = self.get_expected_response_length(data) File "pymodbus/framer/rtu_framer.py", line 320, in get_expected_response_length return pdu_class.calculateRtuFrameSize(data) File "mei_message.py", line 130, in calculateRtuFrameSize _, object_length = struct.unpack(">BB", buffer[size : size + 2]) struct.error: unpack requires a buffer of 2 bytes The caller is expecting an IndexError if there isn't enough data in the packet. So to fix this, catch the struct error and raise an IndexError. --- pymodbus/mei_message.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/pymodbus/mei_message.py b/pymodbus/mei_message.py index 5a1a6b1db..59bbf319a 100644 --- a/pymodbus/mei_message.py +++ b/pymodbus/mei_message.py @@ -125,11 +125,14 @@ def calculateRtuFrameSize(cls, buffer): size = 8 # skip the header information count = int(buffer[7]) - while count > 0: - _, object_length = struct.unpack(">BB", buffer[size : size + 2]) - size += object_length + 2 - count -= 1 - return size + 2 + try: + while count > 0: + _, object_length = struct.unpack(">BB", buffer[size : size + 2]) + size += object_length + 2 + count -= 1 + return size + 2 + except struct.error as exc: + raise IndexError from exc def __init__(self, read_code=None, information=None, **kwargs): """Initialize a new instance.