Skip to content

Commit 431f5fe

Browse files
committed
Fix potential frame parsing issue where an empty payload is still valid
1 parent 469f590 commit 431f5fe

File tree

2 files changed

+33
-9
lines changed

2 files changed

+33
-9
lines changed

tests/test_commands.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,3 +531,22 @@ def test_command_replace_partial():
531531

532532
assert command1.replace() == command1
533533
assert command1.replace(SysId=0x13) == command2
534+
535+
536+
def test_command_possibly_empty_payload():
537+
class TestSubsystem(t.CommandsBase, subsystem=t.Subsystem.SYS):
538+
Test = t.CommandDef(
539+
t.CommandType.AREQ,
540+
0x00,
541+
rsp_schema=(t.Param("Data", t.Bytes, "Can be any length"),),
542+
)
543+
544+
Test = TestSubsystem.Test.Callback
545+
546+
assert Test.from_frame(
547+
frames.GeneralFrame(header=Test.header, data=b"test")
548+
) == Test(Data=t.Bytes(b"test"))
549+
550+
assert Test.from_frame(frames.GeneralFrame(header=Test.header, data=b"")) == Test(
551+
Data=t.Bytes(b"")
552+
)

zigpy_znp/types/commands.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -407,16 +407,21 @@ def from_frame(cls, frame, *, ignore_unparsed=False) -> "CommandBase":
407407
params = {}
408408

409409
for param in cls.schema:
410-
if data:
410+
try:
411411
params[param.name], data = param.type.deserialize(data)
412-
elif not param.optional:
413-
# If we're out of data but the parameter is required, this is bad
414-
raise ValueError(
415-
f"Data has been consumed but required parameters remain: {param}"
416-
)
417-
else:
418-
# If we're out of data and the parameter is optional, we're done
419-
break
412+
except ValueError:
413+
if not data and param.optional:
414+
# If we're out of data and the parameter is optional, we're done
415+
break
416+
elif not data and not param.optional:
417+
# If we're out of data but the parameter is required, this is bad
418+
raise ValueError(
419+
f"Frame data is truncated (parsed {params}),"
420+
f" required parameter remains: {param}"
421+
)
422+
else:
423+
# Otherwise, let the exception happen
424+
raise
420425

421426
if data:
422427
msg = (

0 commit comments

Comments
 (0)