Feature/app data buffer check (#79)
* Added comments and buffer overflow checks * Removed backslashs from C-code.
This commit is contained in:
+107
-41
@@ -40,7 +40,15 @@
|
||||
/** @file rp.c Encode/Decode Read Property and RP ACKs */
|
||||
|
||||
#if BACNET_SVC_RP_A
|
||||
/* encode service */
|
||||
|
||||
/** Encode the service
|
||||
*
|
||||
* @param apdu Pointer to the buffer for encoding.
|
||||
* @param invoke_id Invoke ID
|
||||
* @param rpdata Pointer to the property data to be encoded.
|
||||
*
|
||||
* @return Bytes encoded or zero on error.
|
||||
*/
|
||||
int rp_encode_apdu(
|
||||
uint8_t *apdu, uint8_t invoke_id, BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
@@ -60,6 +68,7 @@ int rp_encode_apdu(
|
||||
rpdata->object_type, rpdata->object_instance);
|
||||
apdu_len += len;
|
||||
}
|
||||
/* The value should be in the range of 0 to 4194303. */
|
||||
if (rpdata->object_property <= MAX_BACNET_PROPERTY_ID) {
|
||||
/* check bounds so that we could create malformed
|
||||
messages for testing */
|
||||
@@ -79,7 +88,14 @@ int rp_encode_apdu(
|
||||
}
|
||||
#endif
|
||||
|
||||
/* decode the service request only */
|
||||
/** Decode the service request only
|
||||
*
|
||||
* @param apdu Pointer to the buffer for encoding.
|
||||
* @param apdu_len Count of valid bytes inthe buffer.
|
||||
* @param rpdata Pointer to the property data to be encoded.
|
||||
*
|
||||
* @return Bytes decoded or zero on error.
|
||||
*/
|
||||
int rp_decode_service_request(
|
||||
uint8_t *apdu, unsigned apdu_len, BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
@@ -143,7 +159,14 @@ int rp_decode_service_request(
|
||||
return (int)len;
|
||||
}
|
||||
|
||||
/* alternate method to encode the ack without extra buffer */
|
||||
/** Alternate method to encode the ack without extra buffer.
|
||||
*
|
||||
* @param apdu Pointer to the buffer for encoding.
|
||||
* @param invoke_id Invoke Id
|
||||
* @param rpdata Pointer to the property data to be encoded.
|
||||
*
|
||||
* @return Bytes decoded or zero on error.
|
||||
*/
|
||||
int rp_ack_encode_apdu_init(
|
||||
uint8_t *apdu, uint8_t invoke_id, BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
@@ -176,7 +199,15 @@ int rp_ack_encode_apdu_init(
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/* note: encode the application tagged data yourself */
|
||||
/** Encode the closing tag for the object property.
|
||||
* Note: Encode the application tagged data yourself.
|
||||
*
|
||||
* @param apdu Pointer to the buffer for encoding.
|
||||
* @param invoke_id Invoke Id
|
||||
* @param rpdata Pointer to the property data to be encoded.
|
||||
*
|
||||
* @return Bytes encoded or zero on error.
|
||||
*/
|
||||
int rp_ack_encode_apdu_object_property_end(uint8_t *apdu)
|
||||
{
|
||||
int apdu_len = 0; /* total length of the apdu, return value */
|
||||
@@ -188,17 +219,31 @@ int rp_ack_encode_apdu_object_property_end(uint8_t *apdu)
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/** Encode the acknowledge.
|
||||
*
|
||||
* @param apdu Pointer to the buffer for encoding.
|
||||
* @param invoke_id Invoke Id
|
||||
* @param rpdata Pointer to the property data to be encoded.
|
||||
*
|
||||
* @return Bytes encoded or zero on error.
|
||||
*/
|
||||
int rp_ack_encode_apdu(
|
||||
uint8_t *apdu, uint8_t invoke_id, BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int imax = 0;
|
||||
int len = 0; /* length of each encoding */
|
||||
int apdu_len = 0; /* total length of the apdu, return value */
|
||||
|
||||
if (apdu) {
|
||||
/* Do the initial encoding */
|
||||
apdu_len = rp_ack_encode_apdu_init(apdu, invoke_id, rpdata);
|
||||
/* propertyValue */
|
||||
for (len = 0; len < rpdata->application_data_len; len++) {
|
||||
/* propertyValue
|
||||
* double check maximum possible */
|
||||
imax = rpdata->application_data_len;
|
||||
if (imax > (MAX_APDU - apdu_len - 2)) {
|
||||
imax = (MAX_APDU - apdu_len - 2);
|
||||
}
|
||||
for (len = 0; len < imax; len++) {
|
||||
apdu[apdu_len++] = rpdata->application_data[len];
|
||||
}
|
||||
apdu_len += encode_closing_tag(&apdu[apdu_len], 3);
|
||||
@@ -231,41 +276,62 @@ int rp_ack_decode_service_request(uint8_t *apdu,
|
||||
uint32_t property = 0; /* for decoding */
|
||||
BACNET_UNSIGNED_INTEGER unsigned_value = 0; /* for decoding */
|
||||
|
||||
/* FIXME: check apdu_len against the len during decode */
|
||||
/* Tag 0: Object ID */
|
||||
if (!decode_is_context_tag(&apdu[0], 0)) {
|
||||
return -1;
|
||||
}
|
||||
len = 1;
|
||||
len += decode_object_id(&apdu[len], &object_type, &rpdata->object_instance);
|
||||
rpdata->object_type = object_type;
|
||||
/* Tag 1: Property ID */
|
||||
len +=
|
||||
decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type);
|
||||
if (tag_number != 1) {
|
||||
return -1;
|
||||
}
|
||||
len += decode_enumerated(&apdu[len], len_value_type, &property);
|
||||
rpdata->object_property = (BACNET_PROPERTY_ID)property;
|
||||
/* Tag 2: Optional Array Index */
|
||||
tag_len =
|
||||
decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type);
|
||||
if (tag_number == 2) {
|
||||
len += tag_len;
|
||||
len += decode_unsigned(&apdu[len], len_value_type, &unsigned_value);
|
||||
rpdata->array_index = (BACNET_ARRAY_INDEX)unsigned_value;
|
||||
} else {
|
||||
rpdata->array_index = BACNET_ARRAY_ALL;
|
||||
}
|
||||
/* Tag 3: opening context tag */
|
||||
if (decode_is_opening_tag_number(&apdu[len], 3)) {
|
||||
/* a tag number of 3 is not extended so only one octet */
|
||||
len++;
|
||||
/* don't decode the application tag number or its data here */
|
||||
rpdata->application_data = &apdu[len];
|
||||
rpdata->application_data_len = apdu_len - len - 1 /*closing tag */;
|
||||
/* len includes the data and the closing tag */
|
||||
len = apdu_len;
|
||||
/* Check basics. */
|
||||
if (apdu && (apdu_len >= 8 /*minimum*/)) {
|
||||
/* Tag 0: Object ID */
|
||||
if (!decode_is_context_tag(&apdu[0], 0)) {
|
||||
return -1;
|
||||
}
|
||||
len = 1;
|
||||
len += decode_object_id(&apdu[len], &object_type, &rpdata->object_instance);
|
||||
rpdata->object_type = object_type;
|
||||
/* Tag 1: Property ID */
|
||||
if (len >= apdu_len) {
|
||||
return -1;
|
||||
}
|
||||
len +=
|
||||
decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type);
|
||||
if (tag_number != 1) {
|
||||
return -1;
|
||||
}
|
||||
if (len >= apdu_len) {
|
||||
return -1;
|
||||
}
|
||||
len += decode_enumerated(&apdu[len], len_value_type, &property);
|
||||
rpdata->object_property = (BACNET_PROPERTY_ID)property;
|
||||
/* Tag 2: Optional Array Index */
|
||||
if (len >= apdu_len) {
|
||||
return -1;
|
||||
}
|
||||
tag_len =
|
||||
decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type);
|
||||
if (tag_number == 2) {
|
||||
len += tag_len;
|
||||
len += decode_unsigned(&apdu[len], len_value_type, &unsigned_value);
|
||||
rpdata->array_index = (BACNET_ARRAY_INDEX)unsigned_value;
|
||||
} else {
|
||||
rpdata->array_index = BACNET_ARRAY_ALL;
|
||||
}
|
||||
/* Tag 3: opening context tag */
|
||||
if (len >= apdu_len) {
|
||||
return -1;
|
||||
}
|
||||
if (decode_is_opening_tag_number(&apdu[len], 3)) {
|
||||
/* a tag number of 3 is not extended so only one octet */
|
||||
len++;
|
||||
/* don't decode the application tag number or its data here */
|
||||
rpdata->application_data = &apdu[len];
|
||||
/* Just to ensure we do not create a wrapped over value here. */
|
||||
if (len < apdu_len) {
|
||||
rpdata->application_data_len = apdu_len - len - 1 /*closing tag */;
|
||||
} else {
|
||||
rpdata->application_data_len = 0;
|
||||
}
|
||||
/* len includes the data and the closing tag */
|
||||
len = apdu_len;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user