[libbacnet]: bacapp_data_len() + bacnet_tag_number_and_value_decode() (#453)

* Bugfix: bacapp_data_len() + bacnet_tag_number_and_value_decode()

* Fix bacnet_tag_number_and_value_decode function.
Add read buffer safe functions for opening, closing, context specific tags.
Fix bacapp_data_len function changes as indicated by unit testing.

* refactor bacapp_data_len
---------
Co-authored-by: Steve Karg <skarg@users.sourceforge.net>
This commit is contained in:
anthony-crystalpeak
2023-07-31 14:50:14 -07:00
committed by GitHub
parent 28de333b6e
commit acb3b0f57d
4 changed files with 134 additions and 48 deletions
+54 -37
View File
@@ -1520,54 +1520,71 @@ int bacapp_data_len(
uint8_t opening_tag_number = 0;
uint8_t opening_tag_number_counter = 0;
uint32_t value = 0;
bool total_len_enable = false;
if (IS_OPENING_TAG(apdu[0])) {
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 = 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 = bacnet_tag_number_and_value_decode(&apdu[apdu_len],
apdu_len_max - apdu_len, &tag_number, &value);
if (tag_number == opening_tag_number) {
if (!apdu) {
return BACNET_STATUS_ERROR;
}
if (apdu_len_max <= apdu_len) {
/* error: exceeding our buffer limit */
return BACNET_STATUS_ERROR;
}
if (!bacnet_is_opening_tag(apdu, apdu_len_max)) {
/* error: opening tag is missing */
return BACNET_STATUS_ERROR;
}
do {
if (bacnet_is_opening_tag(apdu, apdu_len_max)) {
len = bacnet_tag_number_and_value_decode(apdu,
apdu_len_max - apdu_len, &tag_number, &value);
if (opening_tag_number_counter == 0) {
opening_tag_number = tag_number;
opening_tag_number_counter = 1;
total_len_enable = false;
} else if (tag_number == opening_tag_number) {
total_len_enable = true;
opening_tag_number_counter++;
}
} else if (bacnet_is_closing_tag(apdu, apdu_len_max)) {
len = bacnet_tag_number_and_value_decode(apdu,
apdu_len_max - apdu_len, &tag_number, &value);
if (tag_number == opening_tag_number) {
if (opening_tag_number_counter > 0) {
opening_tag_number_counter--;
}
} else if (IS_CONTEXT_SPECIFIC(apdu[apdu_len])) {
}
total_len_enable = true;
} else if (bacnet_is_context_specific(apdu, apdu_len_max)) {
#if defined(BACAPP_TYPES_EXTRA)
/* context-specific tagged data */
len = bacapp_decode_context_data_len(
&apdu[apdu_len], apdu_len_max - apdu_len, property);
/* context-specific tagged data */
len = bacapp_decode_context_data_len(
apdu, apdu_len_max - apdu_len, property);
total_len_enable = true;
#endif
} else {
/* application tagged data */
len = bacapp_decode_application_data_len(
apdu, apdu_len_max - apdu_len);
total_len_enable = true;
}
if (opening_tag_number_counter > 0) {
if (len > 0) {
if (total_len_enable) {
total_len += len;
}
} else {
/* application tagged data */
len = bacapp_decode_application_data_len(
&apdu[apdu_len], apdu_len_max - apdu_len);
/* error: len is not incrementing */
return BACNET_STATUS_ERROR;
}
apdu_len += len;
if (opening_tag_number_counter) {
if (len > 0) {
total_len += len;
} else {
/* error: len is not incrementing */
total_len = BACNET_STATUS_ERROR;
break;
}
}
if ((unsigned)apdu_len > apdu_len_max) {
if (apdu_len_max <= apdu_len) {
/* error: exceeding our buffer limit */
total_len = BACNET_STATUS_ERROR;
break;
return BACNET_STATUS_ERROR;
}
apdu += len;
}
}
} while (opening_tag_number_counter > 0);
return total_len;
}