Bugfix/bacnet array encoding overflows (#414)
* Add common BACnetARRAY encode function to fix Device object list buffer overflow. Refactor device, analog-output, access-door and binary-output objects to use common BACnetARRAY encoder. * Fix non-POSIX builds (win32). * Cleanup some ports/stm32 build warnings --------- Co-authored-by: Steve Karg <skarg@users.sourceforge.net>
This commit is contained in:
@@ -254,54 +254,96 @@ static bool dlmstp_compare_data_expecting_reply(uint8_t *request_pdu,
|
||||
};
|
||||
struct DER_compare_t request;
|
||||
struct DER_compare_t reply;
|
||||
bool request_segmented = false;
|
||||
bool reply_segmented = false;
|
||||
|
||||
/* decode the request data */
|
||||
request.address.mac[0] = src_address;
|
||||
request.address.mac_len = 1;
|
||||
offset = npdu_decode(
|
||||
&request_pdu[0], NULL, &request.address, &request.npdu_data);
|
||||
offset = bacnet_npdu_decode(request_pdu, request_pdu_len, NULL,
|
||||
&request.address, &request.npdu_data);
|
||||
if (request.npdu_data.network_layer_message) {
|
||||
return false;
|
||||
}
|
||||
if (offset >= request_pdu_len) {
|
||||
return false;
|
||||
}
|
||||
request.pdu_type = request_pdu[offset] & 0xF0;
|
||||
if (request.pdu_type != PDU_TYPE_CONFIRMED_SERVICE_REQUEST) {
|
||||
return false;
|
||||
}
|
||||
if (request_pdu[offset] & BIT(3)) {
|
||||
request_segmented = true;
|
||||
}
|
||||
if ((offset + 2) >= request_pdu_len) {
|
||||
return false;
|
||||
}
|
||||
request.invoke_id = request_pdu[offset + 2];
|
||||
/* segmented message? */
|
||||
if (request_pdu[offset] & BIT(3))
|
||||
if (request_segmented) {
|
||||
if ((offset + 5) >= request_pdu_len) {
|
||||
return false;
|
||||
}
|
||||
request.service_choice = request_pdu[offset + 5];
|
||||
else
|
||||
} else {
|
||||
if ((offset + 3) >= request_pdu_len) {
|
||||
return false;
|
||||
}
|
||||
request.service_choice = request_pdu[offset + 3];
|
||||
}
|
||||
/* decode the reply data */
|
||||
reply.address.mac[0] = dest_address;
|
||||
reply.address.mac_len = 1;
|
||||
offset = npdu_decode(&reply_pdu[0], &reply.address, NULL, &reply.npdu_data);
|
||||
offset = bacnet_npdu_decode(
|
||||
reply_pdu, reply_pdu_len, &reply.address, NULL, &reply.npdu_data);
|
||||
if (reply.npdu_data.network_layer_message) {
|
||||
return false;
|
||||
}
|
||||
if (offset >= request_pdu_len) {
|
||||
return false;
|
||||
}
|
||||
reply.pdu_type = reply_pdu[offset] & 0xF0;
|
||||
if (reply_pdu[offset] & BIT(3)) {
|
||||
reply_segmented = true;
|
||||
}
|
||||
/* reply could be a lot of things:
|
||||
confirmed, simple ack, abort, reject, error */
|
||||
reply.pdu_type = reply_pdu[offset] & 0xF0;
|
||||
switch (reply.pdu_type) {
|
||||
case PDU_TYPE_SIMPLE_ACK:
|
||||
if ((offset + 2) >= request_pdu_len) {
|
||||
return false;
|
||||
}
|
||||
reply.invoke_id = reply_pdu[offset + 1];
|
||||
reply.service_choice = reply_pdu[offset + 2];
|
||||
break;
|
||||
case PDU_TYPE_COMPLEX_ACK:
|
||||
reply.invoke_id = reply_pdu[offset + 1];
|
||||
/* segmented message? */
|
||||
if (reply_pdu[offset] & BIT(3))
|
||||
if (reply_segmented) {
|
||||
if ((offset + 4) >= request_pdu_len) {
|
||||
return false;
|
||||
}
|
||||
reply.invoke_id = reply_pdu[offset + 1];
|
||||
reply.service_choice = reply_pdu[offset + 4];
|
||||
else
|
||||
} else {
|
||||
if ((offset + 2) >= request_pdu_len) {
|
||||
return false;
|
||||
}
|
||||
reply.invoke_id = reply_pdu[offset + 1];
|
||||
reply.service_choice = reply_pdu[offset + 2];
|
||||
}
|
||||
break;
|
||||
case PDU_TYPE_ERROR:
|
||||
if ((offset + 2) >= request_pdu_len) {
|
||||
return false;
|
||||
}
|
||||
reply.invoke_id = reply_pdu[offset + 1];
|
||||
reply.service_choice = reply_pdu[offset + 2];
|
||||
break;
|
||||
case PDU_TYPE_REJECT:
|
||||
case PDU_TYPE_ABORT:
|
||||
if ((offset + 1) >= request_pdu_len) {
|
||||
return false;
|
||||
}
|
||||
reply.invoke_id = reply_pdu[offset + 1];
|
||||
break;
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user