diff --git a/code-reviews/Driver.AbLegacy/findings.md b/code-reviews/Driver.AbLegacy/findings.md index a1d8028..8759f10 100644 --- a/code-reviews/Driver.AbLegacy/findings.md +++ b/code-reviews/Driver.AbLegacy/findings.md @@ -117,7 +117,7 @@ reject file numbers on I/O/S, and restrict which file letters may carry a sub-el | Severity | Medium | | Category | Correctness & logic bugs | | Location | `LibplctagLegacyTagRuntime.cs:36-37` | -| Status | Open | +| Status | Resolved | **Description:** `DecodeValue` for `AbLegacyDataType.Bit` with `bitIndex == null` returns `_tag.GetInt8(0) != 0`. A bit-file element (`B3:0/0`) is a single bit inside @@ -132,7 +132,7 @@ but a `Bit`-typed tag configured with an address that has no `/bit` suffix (e.g. bit suffix on `Bit`-typed tags (validate in `CreateInstance`/`DiscoverAsync`) or decode the full 16-bit word and test bit 0. -**Resolution:** _(open)_ +**Resolution:** Resolved 2026-05-22 — `DecodeValue` for `Bit` with no `bitIndex` now reads the full 16-bit word via `GetInt16(0)` and tests bit 0, avoiding the silent half-word truncation from `GetInt8`. ### Driver.AbLegacy-005 diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy/LibplctagLegacyTagRuntime.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy/LibplctagLegacyTagRuntime.cs index 3f8e1aa..d28227a 100644 --- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy/LibplctagLegacyTagRuntime.cs +++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy/LibplctagLegacyTagRuntime.cs @@ -33,9 +33,13 @@ internal sealed class LibplctagLegacyTagRuntime : IAbLegacyTagRuntime public object? DecodeValue(AbLegacyDataType type, int? bitIndex) => type switch { + // When a bit suffix is present (e.g. B3:0/5) libplctag resolves the individual bit and + // GetBit returns it directly. When there is no suffix the caller addressed a Bit-typed + // tag without an explicit bit index; read the full 16-bit word and test bit 0 — GetInt8 + // only covers the low byte and silently misses any bit set in bits 8..15. AbLegacyDataType.Bit => bitIndex is int bit ? _tag.GetBit(bit) - : _tag.GetInt8(0) != 0, + : (_tag.GetInt16(0) & 1) != 0, AbLegacyDataType.Int or AbLegacyDataType.AnalogInt => (int)_tag.GetInt16(0), AbLegacyDataType.Long => _tag.GetInt32(0), AbLegacyDataType.Float => _tag.GetFloat32(0),