From a81bbd4de05065d267e3c48e20d741d2b8e0a7f2 Mon Sep 17 00:00:00 2001 From: puddly <32534428+puddly@users.noreply.github.com> Date: Thu, 5 Dec 2024 13:46:34 -0500 Subject: [PATCH] Fix XNCP parsing for hacked LIDL gateway (#657) --- bellows/ezsp/xncp.py | 6 ++++++ tests/test_xncp.py | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/bellows/ezsp/xncp.py b/bellows/ezsp/xncp.py index ca9da4dd..d50f0575 100644 --- a/bellows/ezsp/xncp.py +++ b/bellows/ezsp/xncp.py @@ -67,6 +67,12 @@ def from_payload(cls, payload: XncpCommandPayload) -> XncpCommand: def from_bytes(cls, data: bytes) -> XncpCommand: command_id, data = XncpCommandId.deserialize(data) status, data = EmberStatus.deserialize(data) + + if command_id not in COMMANDS: + raise ValueError( + f"Unknown XNCP command ID: 0x{command_id:04X} (payload {data!r})" + ) + payload, rest = COMMANDS[command_id].deserialize(data) if rest: diff --git a/tests/test_xncp.py b/tests/test_xncp.py index 61f5b7df..23aa846c 100644 --- a/tests/test_xncp.py +++ b/tests/test_xncp.py @@ -48,6 +48,20 @@ async def test_xncp_failure_multiprotocol(ezsp_f: EZSP) -> None: ] +async def test_xncp_failure_lidl(ezsp_f: EZSP) -> None: + """Test XNCP failure with hacked LIDL gateway.""" + ezsp_f._mock_commands["customFrame"] = customFrame = AsyncMock( + return_value=[t.EmberStatus.SUCCESS, b"\x00\x01\x03"] + ) + + with pytest.raises(InvalidCommandError): + await ezsp_f.xncp_get_supported_firmware_features() + + assert customFrame.mock_calls == [ + call(xncp.XncpCommand.from_payload(xncp.GetSupportedFeaturesReq()).serialize()) + ] + + async def test_xncp_failure_unknown(ezsp_f: EZSP) -> None: """Test XNCP failure, unknown command.""" ezsp_f._mock_commands["customFrame"] = customFrame = AsyncMock(