Hello
When reading a TREND_LOG that contains a special log record (e.g. log-interrupted), records after it are silently missing from the result — no error, no warning.
I spent some time debugging this with Wireshark and found that the raw UDP packet is perfectly valid and complete. The issue is in decodeRange.
What's happening
Special log records don't have status flags. A normal record ends with:
1f 2a 04 00 ← closing tag 1, opening tag 2, BIT_STRING, closing tag 2
A special record ends with just:
1f ← closing tag 1, nothing after
But decodeRange unconditionally consumes 2 tags after the datum value without validating their tag numbers. So it reads into the bytes of the next record, shifts the offset by an unpredictable amount (depends on the byte values that follow), and loses sync for everything after.
The behavior is non-deterministic — sometimes records after the special one are silently dropped, sometimes the buffer appears truncated. Took a while to figure out why the same code would behave differently depending on which records were in the response.
Reproduction
const response = await client.readRange(
{ address: '10.x.x.x:47808' },
{ type: bacnet.ObjectType.TREND_LOG, instance: 100101 },
startIndex, 20,
{}
);
// response contains fewer records than expected
// no error thrown
// Wireshark shows the full response is received correctly
Thanks so much for the patch ;-)
Thomas
Hello
When reading a
TREND_LOGthat contains a special log record (e.g.log-interrupted), records after it are silently missing from the result — no error, no warning.I spent some time debugging this with Wireshark and found that the raw UDP packet is perfectly valid and complete. The issue is in
decodeRange.What's happening
Special log records don't have status flags. A normal record ends with:
A special record ends with just:
But
decodeRangeunconditionally consumes 2 tags after the datum value without validating their tag numbers. So it reads into the bytes of the next record, shifts the offset by an unpredictable amount (depends on the byte values that follow), and loses sync for everything after.The behavior is non-deterministic — sometimes records after the special one are silently dropped, sometimes the buffer appears truncated. Took a while to figure out why the same code would behave differently depending on which records were in the response.
Reproduction