Feature/app data buffer check (#79)

* Added comments and buffer overflow checks

* Removed backslashs from C-code.
This commit is contained in:
Roy Schneider
2020-04-28 15:45:03 +02:00
committed by GitHub
parent 89929ee802
commit 0abcbea971
20 changed files with 1588 additions and 635 deletions
+139 -17
View File
@@ -48,6 +48,15 @@ COV Subscribe Property
COV Notification
Unconfirmed COV Notification
*/
/**
* Encode APDU for notification.
*
* @param apdu Pointer to the buffer.
* @param data Pointer to the data to encode.
*
* @return bytes encoded or zero on error.
*/
static int notify_encode_apdu(
uint8_t *apdu, unsigned max_apdu_len, BACNET_COV_DATA *data)
{
@@ -122,6 +131,16 @@ static int notify_encode_apdu(
return apdu_len;
}
/**
* Encode APDU for confirmed notification.
*
* @param apdu Pointer to the buffer.
* @param max_apdu_len Buffer size.
* @param invoke_id ID to invoke for notification
* @param data Pointer to the data to encode.
*
* @return bytes encoded or zero on error.
*/
int ccov_notify_encode_apdu(uint8_t *apdu,
unsigned max_apdu_len,
uint8_t invoke_id,
@@ -149,6 +168,15 @@ int ccov_notify_encode_apdu(uint8_t *apdu,
return apdu_len;
}
/**
* Encode APDU for unconfirmed notification.
*
* @param apdu Pointer to the buffer.
* @param max_apdu_len Buffer size.
* @param data Pointer to the data to encode.
*
* @return bytes encoded or zero on error.
*/
int ucov_notify_encode_apdu(
uint8_t *apdu, unsigned max_apdu_len, BACNET_COV_DATA *data)
{
@@ -172,8 +200,16 @@ int ucov_notify_encode_apdu(
return apdu_len;
}
/* decode the service request only */
/* COV and Unconfirmed COV are the same */
/**
* Decode the COV-service request only.
* Note: COV and Unconfirmed COV are the same.
*
* @param apdu Pointer to the buffer.
* @param apdu_len Count of valid bytes in the buffer.
* @param data Pointer to the data to store the decoded values.
*
* @return Bytes decoded or Zero/BACNET_STATUS_ERROR on error.
*/
int cov_notify_decode_service_request(
uint8_t *apdu, unsigned apdu_len, BACNET_COV_DATA *data)
{
@@ -187,7 +223,7 @@ int cov_notify_decode_service_request(
BACNET_PROPERTY_VALUE *value = NULL; /* value in list */
BACNET_APPLICATION_DATA_VALUE *app_data = NULL;
if (apdu_len && data) {
if ((apdu_len > 2) && data) {
/* tag 0 - subscriberProcessIdentifier */
if (decode_is_context_tag(&apdu[len], 0)) {
len += decode_tag_number_and_value(
@@ -198,6 +234,9 @@ int cov_notify_decode_service_request(
return BACNET_STATUS_ERROR;
}
/* tag 1 - initiatingDeviceIdentifier */
if (len >= (int)apdu_len) {
return BACNET_STATUS_ERROR;
}
if (decode_is_context_tag(&apdu[len], 1)) {
len += decode_tag_number_and_value(
&apdu[len], &tag_number, &len_value);
@@ -210,6 +249,9 @@ int cov_notify_decode_service_request(
return BACNET_STATUS_ERROR;
}
/* tag 2 - monitoredObjectIdentifier */
if (len >= (int)apdu_len) {
return BACNET_STATUS_ERROR;
}
if (decode_is_context_tag(&apdu[len], 2)) {
len += decode_tag_number_and_value(
&apdu[len], &tag_number, &len_value);
@@ -220,6 +262,9 @@ int cov_notify_decode_service_request(
return BACNET_STATUS_ERROR;
}
/* tag 3 - timeRemaining */
if (len >= (int)apdu_len) {
return BACNET_STATUS_ERROR;
}
if (decode_is_context_tag(&apdu[len], 3)) {
len += decode_tag_number_and_value(
&apdu[len], &tag_number, &len_value);
@@ -242,6 +287,9 @@ int cov_notify_decode_service_request(
}
while (value != NULL) {
/* tag 0 - propertyIdentifier */
if (len >= (int)apdu_len) {
return BACNET_STATUS_ERROR;
}
if (decode_is_context_tag(&apdu[len], 0)) {
len += decode_tag_number_and_value(
&apdu[len], &tag_number, &len_value);
@@ -251,6 +299,9 @@ int cov_notify_decode_service_request(
return BACNET_STATUS_ERROR;
}
/* tag 1 - propertyArrayIndex OPTIONAL */
if (len >= (int)apdu_len) {
return BACNET_STATUS_ERROR;
}
if (decode_is_context_tag(&apdu[len], 1)) {
len += decode_tag_number_and_value(
&apdu[len], &tag_number, &len_value);
@@ -260,6 +311,9 @@ int cov_notify_decode_service_request(
value->propertyArrayIndex = BACNET_ARRAY_ALL;
}
/* tag 2: opening context tag - value */
if (len >= (int)apdu_len) {
return BACNET_STATUS_ERROR;
}
if (!decode_is_opening_tag_number(&apdu[len], 2)) {
return BACNET_STATUS_ERROR;
}
@@ -283,6 +337,9 @@ int cov_notify_decode_service_request(
/* a tag number of 2 is not extended so only one octet */
len++;
/* tag 3 - priority OPTIONAL */
if (len >= (int)apdu_len) {
return BACNET_STATUS_ERROR;
}
if (decode_is_context_tag(&apdu[len], 3)) {
len += decode_tag_number_and_value(
&apdu[len], &tag_number, &len_value);
@@ -330,6 +387,16 @@ SubscribeCOV-Request ::= SEQUENCE {
}
*/
/**
* Encode the COV-service request.
* Note: COV and Unconfirmed COV are the same.
*
* @param apdu Pointer to the buffer.
* @param invoke_id Invoke ID
* @param data Pointer to the data to store the decoded values.
*
* @return Bytes encoded or zero on error.
*/
int cov_subscribe_encode_apdu(uint8_t *apdu,
unsigned max_apdu_len,
uint8_t invoke_id,
@@ -372,7 +439,15 @@ int cov_subscribe_encode_apdu(uint8_t *apdu,
return apdu_len;
}
/* decode the service request only */
/**
* Decode the subscribe-service request only.
*
* @param apdu Pointer to the buffer.
* @param apdu_len Count of valid bytes in the buffer.
* @param data Pointer to the data to store the decoded values.
*
* @return Bytes decoded or Zero/BACNET_STATUS_ERROR on error.
*/
int cov_subscribe_decode_service_request(
uint8_t *apdu, unsigned apdu_len, BACNET_SUBSCRIBE_COV_DATA *data)
{
@@ -382,7 +457,7 @@ int cov_subscribe_decode_service_request(
BACNET_UNSIGNED_INTEGER unsigned_value = 0;
BACNET_OBJECT_TYPE decoded_type = OBJECT_NONE;
if (apdu_len && data) {
if ((apdu_len > 2) && data) {
/* tag 0 - subscriberProcessIdentifier */
if (decode_is_context_tag(&apdu[len], 0)) {
len += decode_tag_number_and_value(
@@ -394,6 +469,9 @@ int cov_subscribe_decode_service_request(
return BACNET_STATUS_REJECT;
}
/* tag 1 - monitoredObjectIdentifier */
if ((unsigned) len >= apdu_len) {
return BACNET_STATUS_REJECT;
}
if (decode_is_context_tag(&apdu[len], 1)) {
len += decode_tag_number_and_value(
&apdu[len], &tag_number, &len_value);
@@ -418,11 +496,15 @@ int cov_subscribe_decode_service_request(
data->cancellationRequest = true;
}
/* tag 3 - lifetime - optional */
if (decode_is_context_tag(&apdu[len], 3)) {
len += decode_tag_number_and_value(
&apdu[len], &tag_number, &len_value);
len += decode_unsigned(&apdu[len], len_value, &unsigned_value);
data->lifetime = unsigned_value;
if ((unsigned) len < apdu_len) {
if (decode_is_context_tag(&apdu[len], 3)) {
len += decode_tag_number_and_value(
&apdu[len], &tag_number, &len_value);
len += decode_unsigned(&apdu[len], len_value, &unsigned_value);
data->lifetime = unsigned_value;
} else {
data->lifetime = 0;
}
} else {
data->lifetime = 0;
}
@@ -453,6 +535,16 @@ BACnetPropertyReference ::= SEQUENCE {
*/
/**
* Encode the properties for subscription into the APDU.
*
* @param apdu Pointer to the buffer.
* @param max_apdu_len Buffer size.
* @param invoke_id Invoke Id.
* @param data Pointer to the data to encode.
*
* @return Bytes decoded or Zero/BACNET_STATUS_ERROR on error.
*/
int cov_subscribe_property_encode_apdu(uint8_t *apdu,
unsigned max_apdu_len,
uint8_t invoke_id,
@@ -509,7 +601,15 @@ int cov_subscribe_property_encode_apdu(uint8_t *apdu,
return apdu_len;
}
/* decode the service request only */
/**
* Decode the COV-service property request only.
*
* @param apdu Pointer to the buffer.
* @param apdu_len Count of valid bytes in the buffer.
* @param data Pointer to the data to store the decoded values.
*
* @return Bytes decoded or Zero/BACNET_STATUS_ERROR on error.
*/
int cov_subscribe_property_decode_service_request(
uint8_t *apdu, unsigned apdu_len, BACNET_SUBSCRIBE_COV_DATA *data)
{
@@ -520,7 +620,7 @@ int cov_subscribe_property_decode_service_request(
BACNET_OBJECT_TYPE decoded_type = OBJECT_NONE; /* for decoding */
uint32_t property = 0; /* for decoding */
if (apdu_len && data) {
if ((apdu_len > 2) && data) {
/* tag 0 - subscriberProcessIdentifier */
if (decode_is_context_tag(&apdu[len], 0)) {
len += decode_tag_number_and_value(
@@ -532,6 +632,9 @@ int cov_subscribe_property_decode_service_request(
return BACNET_STATUS_REJECT;
}
/* tag 1 - monitoredObjectIdentifier */
if (len >= (int)apdu_len) {
return BACNET_STATUS_REJECT;
}
if (decode_is_context_tag(&apdu[len], 1)) {
len += decode_tag_number_and_value(
&apdu[len], &tag_number, &len_value);
@@ -543,6 +646,9 @@ int cov_subscribe_property_decode_service_request(
return BACNET_STATUS_REJECT;
}
/* tag 2 - issueConfirmedNotifications - optional */
if (len >= (int)apdu_len) {
return BACNET_STATUS_REJECT;
}
if (decode_is_context_tag(&apdu[len], 2)) {
data->cancellationRequest = false;
len += decode_tag_number_and_value(
@@ -554,6 +660,9 @@ int cov_subscribe_property_decode_service_request(
data->cancellationRequest = true;
}
/* tag 3 - lifetime - optional */
if (len >= (int)apdu_len) {
return BACNET_STATUS_REJECT;
}
if (decode_is_context_tag(&apdu[len], 3)) {
len += decode_tag_number_and_value(
&apdu[len], &tag_number, &len_value);
@@ -563,6 +672,9 @@ int cov_subscribe_property_decode_service_request(
data->lifetime = 0;
}
/* tag 4 - monitoredPropertyIdentifier */
if (len >= (int)apdu_len) {
return BACNET_STATUS_REJECT;
}
if (!decode_is_opening_tag_number(&apdu[len], 4)) {
data->error_code = ERROR_CODE_REJECT_INVALID_TAG;
return BACNET_STATUS_REJECT;
@@ -570,6 +682,9 @@ int cov_subscribe_property_decode_service_request(
/* a tag number of 4 is not extended so only one octet */
len++;
/* the propertyIdentifier is tag 0 */
if (len >= (int)apdu_len) {
return BACNET_STATUS_REJECT;
}
if (decode_is_context_tag(&apdu[len], 0)) {
len += decode_tag_number_and_value(
&apdu[len], &tag_number, &len_value);
@@ -581,6 +696,9 @@ int cov_subscribe_property_decode_service_request(
return BACNET_STATUS_REJECT;
}
/* the optional array index is tag 1 */
if (len >= (int)apdu_len) {
return BACNET_STATUS_REJECT;
}
if (decode_is_context_tag(&apdu[len], 1)) {
len += decode_tag_number_and_value(
&apdu[len], &tag_number, &len_value);
@@ -597,11 +715,15 @@ int cov_subscribe_property_decode_service_request(
/* a tag number of 4 is not extended so only one octet */
len++;
/* tag 5 - covIncrement - optional */
if (decode_is_context_tag(&apdu[len], 5)) {
data->covIncrementPresent = true;
len += decode_tag_number_and_value(
&apdu[len], &tag_number, &len_value);
len += decode_real(&apdu[len], &data->covIncrement);
if (len < (int)apdu_len) {
if (decode_is_context_tag(&apdu[len], 5)) {
data->covIncrementPresent = true;
len += decode_tag_number_and_value(
&apdu[len], &tag_number, &len_value);
len += decode_real(&apdu[len], &data->covIncrement);
} else {
data->covIncrementPresent = false;
}
} else {
data->covIncrementPresent = false;
}