OpenCyphal / pycyphal

Python implementation of the Cyphal protocol stack.
https://pycyphal.readthedocs.io/
MIT License
119 stars 106 forks source link

UAVCAN/serial: Reception of malformed frames may cause the transport instance to raise unexpected errors and self-terminate #176

Closed pavel-kirienko closed 2 years ago

pavel-kirienko commented 3 years ago

Example:

2021-08-05 18:45:24 0115854 ERR pyuavcan.transport.serial._serial: SerialTransport('socket://localhost:50905', local_node_id=None, service_transfer_multiplier=2, baudrate=9600): Reader thread has failed, the instance with port Serial<id=0x7fcf0bc5b970, open=True>(port='socket://localhost:50905', baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=1.0, xonxoff=False, rtscts=False, dsrdtr=False) will be terminated: Invalid subject ID: 32741                      
Traceback (most recent call last):
  File "/home/pavel/.local/lib/python3.9/site-packages/pyuavcan/transport/serial/_serial.py", line 439, in _reader_thread_func
    parser.process_next_chunk(chunk, chunk_ts)
  File "/home/pavel/.local/lib/python3.9/site-packages/pyuavcan/transport/serial/_stream_parser.py", line 55, in process_next_chunk
    self._finalize(known_invalid=self._outside_frame)
  File "/home/pavel/.local/lib/python3.9/site-packages/pyuavcan/transport/serial/_stream_parser.py", line 80, in _finalize
    parsed = SerialFrame.parse_from_cobs_image(buf)
  File "/home/pavel/.local/lib/python3.9/site-packages/pyuavcan/transport/serial/_frame.py", line 134, in parse_from_cobs_image
    return SerialFrame.parse_from_unescaped_image(memoryview(unescaped_image))
  File "/home/pavel/.local/lib/python3.9/site-packages/pyuavcan/transport/serial/_frame.py", line 171, in parse_from_unescaped_image
    data_specifier = pyuavcan.transport.MessageDataSpecifier(int_data_spec)
  File "<string>", line 4, in __init__
  File "/home/pavel/.local/lib/python3.9/site-packages/pyuavcan/transport/_data_specifier.py", line 26, in __post_init__
    raise ValueError(f"Invalid subject ID: {self.subject_id}")
ValueError: Invalid subject ID: 32741

The solution is to catch ValueError raised from the frame parser method and return None (this behavior is specified in the API contract but implemented incorrectly):

https://github.com/UAVCAN/pyuavcan/blob/76f29d67938a8f3dc6a44eb1c812049fdd757f2e/pyuavcan/transport/serial/_frame.py#L171