weinzierl-engineering / baos

BAOS SDK - http://weinzierl-engineering.github.io/baos
MIT License
40 stars 18 forks source link

Buffer overrun while receiving 14 bytes payload (string value) using BAOSProtocol 1.2 #24

Open timo-schlegel opened 8 months ago

timo-schlegel commented 8 months ago

The kdrive framework runs into an buffer overrun, while receiving events with 14 bytes payload (string values) using BAOSProtocol 1.2 (KNX IP BAOS 770).

Log output: 19:15:51:911 [kdrive.baos.ProtocolDecoder] Rx : IndicationFunctions::DatapointValueIndication F0 C1 A4 01 A4 0E 5A 77 61 6E 67 73 19:15:51:911 [kdrive.baos.StreamConnector12] Error in rxImpl, BAOS Client exception: Invalid Service 19:15:51:911 [kdrive.baos.BaosEvent] BAOS Client exception: Buffer overrun while decoding Datapoint Value (buffer) 19:15:51:911 [kdrive.connector.CallbackThread] Callback thread terminated by unhandled Poco exception [id 2]: BAOS Client exception: Invalid Service 19:15:51:911 [BaosEventListener] BAOS Connector disconnected

The exception occurs in kdrive/src/baos/protocols/Protocol12.cpp line 301:

ServerItem value;
value.id = *ptr++;
const unsigned char stateLength = *ptr++;
value.serviceData = (stateLength << 4) & 0xF0;
value.length = stateLength & 0x0F;

if (static_cast<std::size_t>((ptr + value.length) - begin) > bufferSize)
{
    throw ClientException("Buffer overrun while decoding Datapoint Value (buffer)");
}

Analysis 1: static_cast((ptr + value.length) - begin) returns 16 bufferSize returns 8

Analysis 2: Received packet (from log output above): F0 C1 A4 01 A4 0E 5A 77 61 6E 67 73 -> F0 C1 A4 01 A4 0E (received 1 DatapointValue.Ind with ID 164 and 14 bytes payload length) -> 5A 77 61 6E 67 73 (followed by 6 bytes payload instead of 14 bytes)

Countercheck: Received packet with KnxBAOS DemoClient for protocol 1.x: F0 C1 A4 01 A4 0E 5A 77 61 6E 67 73 62 65 74 72 69 65 62 20 -> F0 C1 A4 01 A4 0E (received 1 DatapointValue.Ind with ID 164 and 14 bytes payload length) -> 5A 77 61 6E 67 73 62 65 74 72 69 65 62 20 (followed by 14 bytes payload)

Conclusion: The buffer size per received datapoint is set to 8 bytes, which is too small to receive a datapoint packet with 16 bytes (1 bytes for DP ID + 1 byte for DP state/length + 14 bytes payload). Therefore the datapoint packet is not fully received, as it does not fit in the buffer.

Question: How can the buffer size be increased?

weinzierl-engineering commented 8 months ago

After looking into it, I probably pinpointed the problem. In the line

bufferIterator = rx(buffer, bufferSize, bufferIterator, buffer[bufferIterator - 1] & 0x07); in file kdrive/src/baos/stream/StreamConnector12.cpp the part

buffer[bufferIterator - 1] & 0x07

reads the length from the buffer.

Since 4 bits are the length (Baos protocol 1.1 Page 18 ) and the mask is wrongly set to 0x07 the highest bit is lost here. Changing it to 0x0F should fix the problem.

Please report back if this change is working for you or not.

timo-schlegel commented 8 months ago

The proposed solution works.

Log output: 18:41:25:209 [kdrive.baos.ProtocolDecoder] Rx : IndicationFunctions::DatapointValueIndication F0 C1 A8 01 A8 0E 5A 77 61 6E 67 73 62 65 74 72 69 65 62 20