Bug #61: add strict decoding for AtomicReadFile, AtomicWriteFile, and DeviceCommunicationControl
This commit is contained in:
+86
-57
@@ -243,7 +243,7 @@ int bacapp_decode_data(uint8_t *apdu,
|
||||
case BACNET_APPLICATION_TAG_OBJECT_ID: {
|
||||
uint16_t object_type = 0;
|
||||
uint32_t instance = 0;
|
||||
len = decode_object_id_safe(
|
||||
len = bacnet_object_id_decode(
|
||||
&apdu[0], len_value_type, &object_type, &instance);
|
||||
value->type.Object_Id.type = object_type;
|
||||
value->type.Object_Id.instance = instance;
|
||||
@@ -271,8 +271,17 @@ int bacapp_decode_data(uint8_t *apdu,
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decode the BACnet Application Data
|
||||
*
|
||||
* @param apdu - buffer of data to be decoded
|
||||
* @param apdu_len_max - number of bytes in the buffer
|
||||
* @param value - decoded value, if decoded
|
||||
*
|
||||
* @return the number of apdu bytes consumed, or #BACNET_STATUS_ERROR
|
||||
*/
|
||||
int bacapp_decode_application_data(
|
||||
uint8_t *apdu, unsigned max_apdu_len, BACNET_APPLICATION_DATA_VALUE *value)
|
||||
uint8_t *apdu, unsigned apdu_len_max, BACNET_APPLICATION_DATA_VALUE *value)
|
||||
{
|
||||
int len = 0;
|
||||
int tag_len = 0;
|
||||
@@ -280,19 +289,27 @@ int bacapp_decode_application_data(
|
||||
uint8_t tag_number = 0;
|
||||
uint32_t len_value_type = 0;
|
||||
|
||||
/* FIXME: use max_apdu_len! */
|
||||
(void)max_apdu_len;
|
||||
if (apdu && value && !IS_CONTEXT_SPECIFIC(*apdu)) {
|
||||
value->context_specific = false;
|
||||
tag_len =
|
||||
decode_tag_number_and_value(&apdu[0], &tag_number, &len_value_type);
|
||||
if (tag_len) {
|
||||
tag_len = bacnet_tag_number_and_value_decode(
|
||||
&apdu[0], apdu_len_max, &tag_number, &len_value_type);
|
||||
if (tag_len > 0) {
|
||||
len += tag_len;
|
||||
value->tag = tag_number;
|
||||
decode_len = bacapp_decode_data(
|
||||
&apdu[len], tag_number, len_value_type, value);
|
||||
if (value->tag != MAX_BACNET_APPLICATION_TAG) {
|
||||
len += decode_len;
|
||||
if (len <= apdu_len_max) {
|
||||
decode_len =
|
||||
bacapp_decode_data_len(NULL, tag_number, len_value_type);
|
||||
if (decode_len <= (apdu_len_max - len)) {
|
||||
decode_len = bacapp_decode_data(
|
||||
&apdu[len], tag_number, len_value_type, value);
|
||||
if (value->tag != MAX_BACNET_APPLICATION_TAG) {
|
||||
len += decode_len;
|
||||
} else {
|
||||
len = BACNET_STATUS_ERROR;
|
||||
}
|
||||
} else {
|
||||
len = BACNET_STATUS_ERROR;
|
||||
}
|
||||
} else {
|
||||
len = BACNET_STATUS_ERROR;
|
||||
}
|
||||
@@ -342,7 +359,7 @@ bool bacapp_decode_application_data_safe(uint8_t *new_apdu,
|
||||
if (value && apdu_len_remaining > 0 &&
|
||||
!IS_CONTEXT_SPECIFIC(apdu[apdu_len])) {
|
||||
value->context_specific = false;
|
||||
tag_len = decode_tag_number_and_value_safe(
|
||||
tag_len = bacnet_tag_number_and_value_decode(
|
||||
&apdu[apdu_len], apdu_len_remaining, &tag_number, &len_value_type);
|
||||
/* If tag_len is zero, then the tag information is truncated */
|
||||
if (tag_len) {
|
||||
@@ -375,34 +392,41 @@ int bacapp_decode_data_len(
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
if (apdu) {
|
||||
switch (tag_data_type) {
|
||||
case BACNET_APPLICATION_TAG_NULL:
|
||||
break;
|
||||
case BACNET_APPLICATION_TAG_BOOLEAN:
|
||||
break;
|
||||
case BACNET_APPLICATION_TAG_UNSIGNED_INT:
|
||||
case BACNET_APPLICATION_TAG_SIGNED_INT:
|
||||
case BACNET_APPLICATION_TAG_REAL:
|
||||
case BACNET_APPLICATION_TAG_DOUBLE:
|
||||
case BACNET_APPLICATION_TAG_OCTET_STRING:
|
||||
case BACNET_APPLICATION_TAG_CHARACTER_STRING:
|
||||
case BACNET_APPLICATION_TAG_BIT_STRING:
|
||||
case BACNET_APPLICATION_TAG_ENUMERATED:
|
||||
case BACNET_APPLICATION_TAG_DATE:
|
||||
case BACNET_APPLICATION_TAG_TIME:
|
||||
case BACNET_APPLICATION_TAG_OBJECT_ID:
|
||||
len = (int)len_value_type;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
(void)apdu;
|
||||
switch (tag_data_type) {
|
||||
case BACNET_APPLICATION_TAG_NULL:
|
||||
break;
|
||||
case BACNET_APPLICATION_TAG_BOOLEAN:
|
||||
break;
|
||||
case BACNET_APPLICATION_TAG_UNSIGNED_INT:
|
||||
case BACNET_APPLICATION_TAG_SIGNED_INT:
|
||||
case BACNET_APPLICATION_TAG_REAL:
|
||||
case BACNET_APPLICATION_TAG_DOUBLE:
|
||||
case BACNET_APPLICATION_TAG_OCTET_STRING:
|
||||
case BACNET_APPLICATION_TAG_CHARACTER_STRING:
|
||||
case BACNET_APPLICATION_TAG_BIT_STRING:
|
||||
case BACNET_APPLICATION_TAG_ENUMERATED:
|
||||
case BACNET_APPLICATION_TAG_DATE:
|
||||
case BACNET_APPLICATION_TAG_TIME:
|
||||
case BACNET_APPLICATION_TAG_OBJECT_ID:
|
||||
len = (int)len_value_type;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int bacapp_decode_application_data_len(uint8_t *apdu, unsigned max_apdu_len)
|
||||
/**
|
||||
* @brief Determine the BACnet Application Data number of APDU bytes consumed
|
||||
*
|
||||
* @param apdu - buffer of data to be decoded
|
||||
* @param apdu_len_max - number of bytes in the buffer
|
||||
*
|
||||
* @return number of bytes decoded, or zero if errors occur
|
||||
*/
|
||||
int bacapp_decode_application_data_len(uint8_t *apdu, unsigned apdu_len_max)
|
||||
{
|
||||
int len = 0;
|
||||
int tag_len = 0;
|
||||
@@ -410,15 +434,13 @@ int bacapp_decode_application_data_len(uint8_t *apdu, unsigned max_apdu_len)
|
||||
uint8_t tag_number = 0;
|
||||
uint32_t len_value_type = 0;
|
||||
|
||||
/* FIXME: use max_apdu_len! */
|
||||
(void)max_apdu_len;
|
||||
if (apdu && !IS_CONTEXT_SPECIFIC(*apdu)) {
|
||||
tag_len =
|
||||
decode_tag_number_and_value(&apdu[0], &tag_number, &len_value_type);
|
||||
if (tag_len) {
|
||||
tag_len = bacnet_tag_number_and_value_decode(
|
||||
&apdu[0], apdu_len_max, &tag_number, &len_value_type);
|
||||
if (tag_len > 0) {
|
||||
len += tag_len;
|
||||
decode_len =
|
||||
bacapp_decode_data_len(&apdu[len], tag_number, len_value_type);
|
||||
bacapp_decode_data_len(NULL, tag_number, len_value_type);
|
||||
len += decode_len;
|
||||
}
|
||||
}
|
||||
@@ -730,8 +752,17 @@ int bacapp_decode_context_data(uint8_t *apdu,
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determine the BACnet Context Data number of APDU bytes consumed
|
||||
*
|
||||
* @param apdu - buffer of data to be decoded
|
||||
* @param apdu_len_max - number of bytes in the buffer
|
||||
* @param property - context property identifier
|
||||
*
|
||||
* @return number of bytes decoded, or zero if errors occur
|
||||
*/
|
||||
int bacapp_decode_context_data_len(
|
||||
uint8_t *apdu, unsigned max_apdu_len, BACNET_PROPERTY_ID property)
|
||||
uint8_t *apdu, unsigned apdu_len_max, BACNET_PROPERTY_ID property)
|
||||
{
|
||||
int apdu_len = 0, len = 0;
|
||||
int tag_len = 0;
|
||||
@@ -739,17 +770,14 @@ int bacapp_decode_context_data_len(
|
||||
uint32_t len_value_type = 0;
|
||||
uint8_t tag = 0;
|
||||
|
||||
/* FIXME: use max_apdu_len! */
|
||||
(void)max_apdu_len;
|
||||
if (apdu && IS_CONTEXT_SPECIFIC(*apdu)) {
|
||||
tag_len =
|
||||
decode_tag_number_and_value(&apdu[0], &tag_number, &len_value_type);
|
||||
tag_len = bacnet_tag_number_and_value_decode(
|
||||
&apdu[0], apdu_len_max, &tag_number, &len_value_type);
|
||||
if (tag_len) {
|
||||
apdu_len = tag_len;
|
||||
tag = bacapp_context_tag_type(property, tag_number);
|
||||
if (tag < MAX_BACNET_APPLICATION_TAG) {
|
||||
len = bacapp_decode_data_len(
|
||||
&apdu[apdu_len], tag, len_value_type);
|
||||
len = bacapp_decode_data_len(NULL, tag, len_value_type);
|
||||
apdu_len += len;
|
||||
} else {
|
||||
apdu_len += len_value_type;
|
||||
@@ -878,7 +906,7 @@ bool bacapp_copy(BACNET_APPLICATION_DATA_VALUE *dest_value,
|
||||
Include a value property identifier for context specific data
|
||||
such as the value received in a WriteProperty request */
|
||||
int bacapp_data_len(
|
||||
uint8_t *apdu, unsigned max_apdu_len, BACNET_PROPERTY_ID property)
|
||||
uint8_t *apdu, unsigned apdu_len_max, BACNET_PROPERTY_ID property)
|
||||
{
|
||||
int len = 0;
|
||||
int total_len = 0;
|
||||
@@ -889,31 +917,32 @@ int bacapp_data_len(
|
||||
uint32_t value = 0;
|
||||
|
||||
if (IS_OPENING_TAG(apdu[0])) {
|
||||
len = decode_tag_number_and_value(&apdu[apdu_len], &tag_number, &value);
|
||||
len = bacnet_tag_number_and_value_decode(
|
||||
&apdu[apdu_len], apdu_len_max - apdu_len, &tag_number, &value);
|
||||
apdu_len += len;
|
||||
opening_tag_number = tag_number;
|
||||
opening_tag_number_counter = 1;
|
||||
while (opening_tag_number_counter) {
|
||||
if (IS_OPENING_TAG(apdu[apdu_len])) {
|
||||
len = decode_tag_number_and_value(
|
||||
&apdu[apdu_len], &tag_number, &value);
|
||||
len = bacnet_tag_number_and_value_decode(&apdu[apdu_len],
|
||||
apdu_len_max - apdu_len, &tag_number, &value);
|
||||
if (tag_number == opening_tag_number) {
|
||||
opening_tag_number_counter++;
|
||||
}
|
||||
} else if (IS_CLOSING_TAG(apdu[apdu_len])) {
|
||||
len = decode_tag_number_and_value(
|
||||
&apdu[apdu_len], &tag_number, &value);
|
||||
len = bacnet_tag_number_and_value_decode(&apdu[apdu_len],
|
||||
apdu_len_max - apdu_len, &tag_number, &value);
|
||||
if (tag_number == opening_tag_number) {
|
||||
opening_tag_number_counter--;
|
||||
}
|
||||
} else if (IS_CONTEXT_SPECIFIC(apdu[apdu_len])) {
|
||||
/* context-specific tagged data */
|
||||
len = bacapp_decode_context_data_len(
|
||||
&apdu[apdu_len], max_apdu_len - apdu_len, property);
|
||||
&apdu[apdu_len], apdu_len_max - apdu_len, property);
|
||||
} else {
|
||||
/* application tagged data */
|
||||
len = bacapp_decode_application_data_len(
|
||||
&apdu[apdu_len], max_apdu_len - apdu_len);
|
||||
&apdu[apdu_len], apdu_len_max - apdu_len);
|
||||
}
|
||||
apdu_len += len;
|
||||
if (opening_tag_number_counter) {
|
||||
@@ -925,7 +954,7 @@ int bacapp_data_len(
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((unsigned)apdu_len > max_apdu_len) {
|
||||
if ((unsigned)apdu_len > apdu_len_max) {
|
||||
/* error: exceeding our buffer limit */
|
||||
total_len = BACNET_STATUS_ERROR;
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user