G1: R01 — guard parsePacketPayload against short payloads

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
This commit is contained in:
Matthew Wolter 2026-04-11 18:26:37 -07:00
parent a571eff4ce
commit c984a78e70

View file

@ -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