Auto: ablegacy-6 — ST string verification + length guard
Verifies libplctag's GetString/SetString round-trips ST file strings (1-word length prefix + 82 ASCII bytes) end-to-end through the driver, and adds a client-side length guard so over-82-char writes return BadOutOfRange instead of being silently truncated by libplctag. - LibplctagLegacyTagRuntime.EncodeValue: throws ArgumentOutOfRangeException for >82-char String writes (StFileMaxStringLength constant). - AbLegacyDriver.WriteAsync: catches ArgumentOutOfRangeException and maps to BadOutOfRange. - AbLegacyStringEncodingTests: 16 unit tests covering empty / 41-char / 82-char / embedded-NUL / non-ASCII reads + writes; over-length writes return BadOutOfRange and never call WriteAsync; both Slc500 and Plc5 family paths exercised. Closes #249 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -237,6 +237,13 @@ public sealed class AbLegacyDriver : IDriver, IReadable, IWritable, ITagDiscover
|
||||
{
|
||||
results[i] = new WriteResult(AbLegacyStatusMapper.BadOutOfRange);
|
||||
}
|
||||
catch (ArgumentOutOfRangeException)
|
||||
{
|
||||
// ST-file string writes exceeding the 82-byte fixed element. Surfaces from
|
||||
// LibplctagLegacyTagRuntime.EncodeValue's length guard; mapped to BadOutOfRange so
|
||||
// the OPC UA client sees a clean rejection rather than a silent truncation.
|
||||
results[i] = new WriteResult(AbLegacyStatusMapper.BadOutOfRange);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
results[i] = new WriteResult(AbLegacyStatusMapper.BadCommunicationError);
|
||||
|
||||
@@ -12,6 +12,15 @@ internal sealed class LibplctagLegacyTagRuntime : IAbLegacyTagRuntime
|
||||
{
|
||||
private readonly Tag _tag;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum payload length for an ST (string) file element on SLC / MicroLogix / PLC-5.
|
||||
/// The on-wire layout is a 1-word length prefix followed by 82 ASCII bytes — libplctag's
|
||||
/// <c>SetString</c> handles the framing internally, but it does NOT validate length, so a
|
||||
/// 93-byte source string would silently truncate. We reject up-front so the OPC UA client
|
||||
/// gets a clean <c>BadOutOfRange</c> rather than a corrupted PLC value.
|
||||
/// </summary>
|
||||
internal const int StFileMaxStringLength = 82;
|
||||
|
||||
public LibplctagLegacyTagRuntime(AbLegacyTagCreateParams p)
|
||||
{
|
||||
_tag = new Tag
|
||||
@@ -87,7 +96,14 @@ internal sealed class LibplctagLegacyTagRuntime : IAbLegacyTagRuntime
|
||||
_tag.SetFloat32(0, Convert.ToSingle(value));
|
||||
break;
|
||||
case AbLegacyDataType.String:
|
||||
_tag.SetString(0, Convert.ToString(value) ?? string.Empty);
|
||||
{
|
||||
var s = Convert.ToString(value) ?? string.Empty;
|
||||
if (s.Length > StFileMaxStringLength)
|
||||
throw new ArgumentOutOfRangeException(
|
||||
nameof(value),
|
||||
$"ST string write exceeds {StFileMaxStringLength}-byte file element capacity (was {s.Length}).");
|
||||
_tag.SetString(0, s);
|
||||
}
|
||||
break;
|
||||
case AbLegacyDataType.TimerElement:
|
||||
case AbLegacyDataType.CounterElement:
|
||||
|
||||
Reference in New Issue
Block a user