From 29a06f004ff05b710f2b7fbc779c88acc1e69133 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E5=85=86=E5=B0=89?= <228127304@qq.com> Date: Wed, 26 Aug 2026 23:04:40 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20FASS2=20=E7=8A=B6=E6=80=81=E5=B8=A7?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C=20XOR?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 错误校验和的 100B 上报不再被当成合法状态解析。 Co-authored-by: Cursor --- .../Protocol/Fass2ProtocolGoldenTests.cs | 18 +++++++++++++++ .../Protocol/Fass2Protocol.cs | 23 +++++++++++++++---- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/StandardScene.Magnetic.Tests/Protocol/Fass2ProtocolGoldenTests.cs b/StandardScene.Magnetic.Tests/Protocol/Fass2ProtocolGoldenTests.cs index 941fe3f..d154a97 100644 --- a/StandardScene.Magnetic.Tests/Protocol/Fass2ProtocolGoldenTests.cs +++ b/StandardScene.Magnetic.Tests/Protocol/Fass2ProtocolGoldenTests.cs @@ -124,6 +124,24 @@ namespace StandardScene.Magnetic.Tests.Protocol Assert.Equal((ushort)500, report.Node.Distance); } + [Fact] + public void TryExtractStateFrame_RejectsBadXor() + { + var frame = Fass2TestFrameBuilder.BuildStateFrame(5, 2, 7, 42); + frame[98] ^= 0xFF; + + Assert.False(Fass2Protocol.TryExtractStateFrame(frame, frame.Length, out _)); + } + + [Fact] + public void ParseState_RejectsBadXor() + { + var frame = Fass2TestFrameBuilder.BuildStateFrame(5, 2, 7, 42); + frame[98] ^= 0xFF; + + Assert.Throws(() => Fass2Protocol.ParseState(frame)); + } + [Fact] public void NodeMessage_ToBytes_FromBytes_RoundTrip() { diff --git a/StandardScene.Magnetic/Protocol/Fass2Protocol.cs b/StandardScene.Magnetic/Protocol/Fass2Protocol.cs index 06fecfc..87a4f08 100644 --- a/StandardScene.Magnetic/Protocol/Fass2Protocol.cs +++ b/StandardScene.Magnetic/Protocol/Fass2Protocol.cs @@ -141,19 +141,27 @@ namespace StandardScene.Magnetic.Protocol continue; } + if (!HasValidStateChecksum(buffer, i)) + { + continue; + } + frame = new byte[StateFrameLength]; Buffer.BlockCopy(buffer, i, frame, 0, StateFrameLength); return true; } - if (length == StateFrameLength && buffer[0] == Begin && buffer[StateFrameLength - 1] == End) + return false; + } + + public static bool HasValidStateChecksum(byte[] bytes, int offset = 0) + { + if (bytes == null || offset < 0 || offset + StateFrameLength > bytes.Length) { - frame = new byte[StateFrameLength]; - Buffer.BlockCopy(buffer, 0, frame, 0, StateFrameLength); - return true; + return false; } - return false; + return bytes[offset + 98] == Xor(bytes, offset + 1, 97); } public static Fass2StateReport ParseState(byte[] bytes) @@ -166,6 +174,11 @@ namespace StandardScene.Magnetic.Protocol { throw new ArgumentException($"invalid FASS2 state frame: begin=0x{bytes[0]:X2}, end=0x{bytes[99]:X2}"); } + if (!HasValidStateChecksum(bytes)) + { + throw new ArgumentException( + $"invalid FASS2 state xor: got=0x{bytes[98]:X2}, expect=0x{Xor(bytes, 1, 97):X2}"); + } var nodeBytes = new byte[25]; Buffer.BlockCopy(bytes, 53, nodeBytes, 0, 25);