From c984a78e70ac17a7f851977980d41b3ac2013dab Mon Sep 17 00:00:00 2001 From: Matthew Wolter Date: Sat, 11 Apr 2026 18:26:37 -0700 Subject: [PATCH] =?UTF-8?q?G1:=20R01=20=E2=80=94=20guard=20parsePacketPayl?= =?UTF-8?q?oad=20against=20short=20payloads?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a 2-byte hard-floor length check at the top of MeshcorePacketParser.parsePacketPayload. The minimum viable payload is 1 header byte + 1 path_byte for a direct route; anything shorter would crash on `path_byte = pbuf.read(1)[0]` (IndexError on the empty buffer). The reader.py LOG_DATA branch only requires `len(data) > 3`, so a 4-byte LOG_DATA frame produces a 1-byte payload here — that path is reachable. The caller in reader.py dereferences log_data['route_type'], ['payload_type'], ['path_len'], and ['path'] immediately after the parse, so an empty log_data would KeyError on the dispatch (caught by the F06 umbrella, but the dispatch would still be skipped). Populate sentinel values matching the existing route_typename = "UNK" pattern in the function before the early return so the caller's downstream lookups don't KeyError, then return early with a debug log. Finding: R01 (S2) File: src/meshcore/meshcore_parser.py --- src/meshcore/meshcore_parser.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/meshcore/meshcore_parser.py b/src/meshcore/meshcore_parser.py index 2139663..715dfd3 100644 --- a/src/meshcore/meshcore_parser.py +++ b/src/meshcore/meshcore_parser.py @@ -42,8 +42,30 @@ class MeshcorePacketParser: Returns : completed log_data """ + # Minimum viable payload is 2 bytes (1 header + 1 path_byte) for a + # direct route. Anything shorter is provably broken — for example, + # the LOG_DATA branch in reader.py only requires `len(data) > 3`, + # which means a 4-byte LOG_DATA frame produces a 1-byte payload + # here, and `path_byte = pbuf.read(1)[0]` further down would raise + # IndexError on the empty buffer. Populate sentinel values so the + # caller's downstream `log_data['route_type']` etc. lookups don't + # KeyError, then return early. + if len(payload) < 2: + logger.debug(f"parsePacketPayload: payload too short ({len(payload)} bytes < 2), returning sentinel log_data") + log_data["route_type"] = -1 + log_data["route_typename"] = "UNK" + log_data["payload_type"] = -1 + log_data["payload_typename"] = "UNK" + log_data["payload_ver"] = 0 + log_data["path_len"] = 0 + log_data["path_hash_size"] = 1 + log_data["path"] = "" + log_data["pkt_payload"] = b"" + log_data["pkt_hash"] = 0 + return log_data + pbuf = io.BytesIO(payload) - + header = pbuf.read(1)[0] route_type = header & 0x03 payload_type = (header & 0x3c) >> 2