Added array size parameter in BACnet array write handlers avoid a duplicate decoding operation. Avoid duplicate checking of array size in object handlers. (#1253)

This commit is contained in:
Steve Karg
2026-03-05 10:15:47 -06:00
committed by GitHub
parent b17a7c6084
commit 8c47e8c9a3
10 changed files with 81 additions and 43 deletions
+3
View File
@@ -152,6 +152,9 @@ The git repositories are hosted at the following sites:
### Changed
* Changed bacnet_array_write() write_function callback API by adding
array size parameter to avoid a duplicate decoding operation.
Removed duplicate checking of array size in object handlers. (#1253)
* Changed bacfile_strdup to bacnet_strdup function to replace POSIX strdup
and update bacfile to use bacnet_strdup. (#1251)
* Changed PositiveInteger present-value datatype to
+5 -5
View File
@@ -5904,8 +5904,8 @@ BACNET_ERROR_CODE bacnet_array_write(
len = bacnet_unsigned_application_decode(
apdu, apdu_size, &unsigned_value);
if (len > 0) {
error_code =
write_function(object_instance, array_index, apdu, apdu_size);
error_code = write_function(
object_instance, array_index, unsigned_value, apdu, apdu_size);
} else if (len == 0) {
error_code = ERROR_CODE_INVALID_DATA_TYPE;
} else {
@@ -5931,7 +5931,7 @@ BACNET_ERROR_CODE bacnet_array_write(
len = decode_function(
object_instance, &apdu[apdu_len], apdu_size - apdu_len);
error_code = write_function(
object_instance, index, &apdu[apdu_len], len);
object_instance, index, array_size, &apdu[apdu_len], len);
if (error_code != ERROR_CODE_SUCCESS) {
break;
}
@@ -5940,8 +5940,8 @@ BACNET_ERROR_CODE bacnet_array_write(
}
} else if (array_index <= array_size) {
/* index was specified; write a single array element */
error_code =
write_function(object_instance, array_index, apdu, apdu_size);
error_code = write_function(
object_instance, array_index, array_size, apdu, apdu_size);
} else {
/* array_index was specified out of range */
error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
+2
View File
@@ -47,6 +47,7 @@ typedef int (*bacnet_array_property_element_decode_function)(
* @param object_instance [in] BACnet network port object instance number
* @param array_index [in] array index to write:
* 0=array size, 1 to N for individual array members
* @param array_size [in] number of elements in the array
* @param application_data [in] encoded element value
* @param application_data_len [in] The size of the encoded element value
* @return BACNET_ERROR_CODE value
@@ -54,6 +55,7 @@ typedef int (*bacnet_array_property_element_decode_function)(
typedef BACNET_ERROR_CODE (*bacnet_array_property_element_write_function)(
uint32_t object_instance,
BACNET_ARRAY_INDEX array_index,
BACNET_UNSIGNED_INTEGER array_size,
uint8_t *application_data,
size_t application_data_len);
+12 -6
View File
@@ -1111,6 +1111,7 @@ static int Channel_List_Of_Object_Property_References_Length(
* @param object_instance [in] BACnet network port object instance number
* @param array_index [in] array index to write:
* 0=array size, 1 to N for individual array members
* @param array_size [in] number of elements in the array, if writing array size
* @param application_data [in] encoded element value
* @param application_data_len [in] The size of the encoded element value
* @return BACNET_ERROR_CODE value
@@ -1118,6 +1119,7 @@ static int Channel_List_Of_Object_Property_References_Length(
static BACNET_ERROR_CODE Channel_List_Of_Object_Property_References_Write(
uint32_t object_instance,
BACNET_ARRAY_INDEX array_index,
BACNET_UNSIGNED_INTEGER array_size,
uint8_t *application_data,
size_t application_data_len)
{
@@ -1130,8 +1132,11 @@ static BACNET_ERROR_CODE Channel_List_Of_Object_Property_References_Write(
pObject = Object_Data(object_instance);
if (pObject) {
if (array_index == 0) {
/* This array is not required to be resizable
through BACnet write services */
(void)array_size;
error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else if (array_index <= CHANNEL_MEMBERS_MAX) {
} else {
len = bacapp_decode_known_property(
application_data, application_data_len, &value, OBJECT_CHANNEL,
PROP_LIST_OF_OBJECT_PROPERTY_REFERENCES);
@@ -1152,8 +1157,6 @@ static BACNET_ERROR_CODE Channel_List_Of_Object_Property_References_Write(
} else {
error_code = ERROR_CODE_ABORT_OTHER;
}
} else {
error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
}
}
@@ -1188,6 +1191,7 @@ static int Channel_Control_Groups_Length(
* @param object_instance [in] BACnet network port object instance number
* @param array_index [in] array index to write:
* 0=array size, 1 to N for individual array members
* @param array_size [in] number of elements in the array, if writing array size
* @param application_data [in] encoded element value
* @param application_data_len [in] The size of the encoded element value
* @return BACNET_ERROR_CODE value
@@ -1195,6 +1199,7 @@ static int Channel_Control_Groups_Length(
static BACNET_ERROR_CODE Channel_Control_Groups_Write(
uint32_t object_instance,
BACNET_ARRAY_INDEX array_index,
BACNET_UNSIGNED_INTEGER array_size,
uint8_t *application_data,
size_t application_data_len)
{
@@ -1208,8 +1213,11 @@ static BACNET_ERROR_CODE Channel_Control_Groups_Write(
pObject = Object_Data(object_instance);
if (pObject) {
if (array_index == 0) {
/* This array is not required to be resizable
through BACnet write services */
(void)array_size;
error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else if (array_index <= CHANNEL_MEMBERS_MAX) {
} else {
len = bacapp_decode_known_property(
application_data, application_data_len, &value, OBJECT_CHANNEL,
PROP_CONTROL_GROUPS);
@@ -1233,8 +1241,6 @@ static BACNET_ERROR_CODE Channel_Control_Groups_Write(
} else {
error_code = ERROR_CODE_ABORT_OTHER;
}
} else {
error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
}
}
+4 -3
View File
@@ -2539,6 +2539,7 @@ static int Device_Configuration_File_Length(
* @param object_instance [in] BACnet object instance number
* @param array_index [in] array index to write:
* 0=array size, 1 to N for individual array members
* @param array_size [in] The total size of the array, if writing array size
* @param application_data [in] encoded element value
* @param application_data_len [in] The size of the encoded element value
* @return BACNET_ERROR_CODE value
@@ -2546,6 +2547,7 @@ static int Device_Configuration_File_Length(
static BACNET_ERROR_CODE Device_Configuration_File_Write(
uint32_t object_instance,
BACNET_ARRAY_INDEX array_index,
BACNET_UNSIGNED_INTEGER array_size,
uint8_t *application_data,
size_t application_data_len)
{
@@ -2558,8 +2560,9 @@ static BACNET_ERROR_CODE Device_Configuration_File_Write(
if (array_index == 0) {
/* This array is not required to be resizable
through BACnet write services */
(void)array_size;
error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else if (array_index <= BACNET_BACKUP_FILE_COUNT) {
} else {
len = bacnet_object_id_application_decode(
application_data, application_data_len, &object_type, &instance);
if (len > 0) {
@@ -2576,8 +2579,6 @@ static BACNET_ERROR_CODE Device_Configuration_File_Write(
} else {
error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else {
error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
}
return error_code;
+4
View File
@@ -1423,6 +1423,8 @@ static int BACnet_Shed_Level_Element_Length(
* @param object_instance [in] BACnet object instance number
* @param array_index [in] array index to write:
* 0=array size, 1 to N for individual array members
* @param array_size [in] The total number of elements in the array,
* if writing array size
* @param application_data [in] encoded element value
* @param application_data_len [in] The size of the encoded element value
* @return BACNET_ERROR_CODE value
@@ -1430,6 +1432,7 @@ static int BACnet_Shed_Level_Element_Length(
static BACNET_ERROR_CODE BACnet_Shed_Level_Element_Write(
uint32_t object_instance,
BACNET_ARRAY_INDEX array_index,
BACNET_UNSIGNED_INTEGER array_size,
uint8_t *application_data,
size_t application_data_len)
{
@@ -1447,6 +1450,7 @@ static BACNET_ERROR_CODE BACnet_Shed_Level_Element_Write(
if (array_index == 0) {
/* This array is not required to be resizable
through BACnet write services */
(void)array_size;
error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else if (array_index <= count) {
len = bacnet_shed_level_decode(
+18 -14
View File
@@ -2107,6 +2107,8 @@ static int BBMD_Broadcast_Distribution_Table_Element_Length(
* @param object_instance [in] BACnet network port object instance number
* @param array_index [in] array index to write:
* 0=array size, 1 to N for individual array members
* @param array_size [in] The total number of elements in the array,
* if writing array size
* @param application_data [in] encoded element value
* @param application_data_len [in] The size of the encoded element value
* @return BACNET_ERROR_CODE value
@@ -2114,13 +2116,13 @@ static int BBMD_Broadcast_Distribution_Table_Element_Length(
static BACNET_ERROR_CODE BBMD_Broadcast_Distribution_Table_Element_Write(
uint32_t object_instance,
BACNET_ARRAY_INDEX array_index,
BACNET_UNSIGNED_INTEGER array_size,
uint8_t *application_data,
size_t application_data_len)
{
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY bdt_entry = { 0 };
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_list;
uint16_t capacity = 0;
int len;
bool status = false;
unsigned index = 0;
@@ -2128,14 +2130,16 @@ static BACNET_ERROR_CODE BBMD_Broadcast_Distribution_Table_Element_Write(
index = Network_Port_Instance_To_Index(object_instance);
if (index < BACNET_NETWORK_PORTS_MAX) {
if (Object_List[index].Network_Type == PORT_TYPE_BIP) {
bdt_list = Object_List[index].Network.IPv4.BBMD_BD_Table;
capacity = bvlc_broadcast_distribution_table_count(bdt_list);
if (array_index == 0) {
error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
} else if (array_index <= capacity) {
/* This array is not required to be resizable
through BACnet write services */
(void)array_size;
error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else {
len = bvlc_decode_broadcast_distribution_table_entry(
application_data, application_data_len, &bdt_entry);
if (len > 0) {
bdt_list = Object_List[index].Network.IPv4.BBMD_BD_Table;
status = bvlc_broadcast_distribution_table_entry_insert(
bdt_list, &bdt_entry, array_index);
if (status) {
@@ -2146,8 +2150,6 @@ static BACNET_ERROR_CODE BBMD_Broadcast_Distribution_Table_Element_Write(
} else {
error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else {
error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
}
} else {
error_code = ERROR_CODE_ABORT_OTHER;
@@ -2320,6 +2322,8 @@ static int BBMD_Foreign_Device_Table_Element_Length(
* @param object_instance [in] BACnet network port object instance number
* @param array_index [in] array index to write:
* 0=array size, 1 to N for individual array members
* @param array_size [in] The total number of elements in the array,
* if writing array size
* @param application_data [in] encoded element value
* @param application_data_len [in] The size of the encoded element value
* @return BACNET_ERROR_CODE value
@@ -2327,13 +2331,13 @@ static int BBMD_Foreign_Device_Table_Element_Length(
static BACNET_ERROR_CODE BBMD_Foreign_Device_Table_Element_Write(
uint32_t object_instance,
BACNET_ARRAY_INDEX array_index,
BACNET_UNSIGNED_INTEGER array_size,
uint8_t *application_data,
size_t application_data_len)
{
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY fdt_entry = { 0 };
BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_list;
uint16_t capacity = 0;
int len;
bool status = false;
unsigned index = 0;
@@ -2341,14 +2345,16 @@ static BACNET_ERROR_CODE BBMD_Foreign_Device_Table_Element_Write(
index = Network_Port_Instance_To_Index(object_instance);
if (index < BACNET_NETWORK_PORTS_MAX) {
if (Object_List[index].Network_Type == PORT_TYPE_BIP) {
fdt_list = Object_List[index].Network.IPv4.BBMD_FD_Table;
capacity = bvlc_foreign_device_table_count(fdt_list);
if (array_index == 0) {
error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
} else if (array_index <= capacity) {
/* This array is not required to be resizable
through BACnet write services */
(void)array_size;
error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else {
len = bvlc_decode_foreign_device_table_entry(
application_data, application_data_len, &fdt_entry);
if (len > 0) {
fdt_list = Object_List[index].Network.IPv4.BBMD_FD_Table;
status = bvlc_foreign_device_table_entry_insert(
fdt_list, &fdt_entry, array_index - 1);
if (status) {
@@ -2359,8 +2365,6 @@ static BACNET_ERROR_CODE BBMD_Foreign_Device_Table_Element_Write(
} else {
error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else {
error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
}
} else {
error_code = ERROR_CODE_ABORT_OTHER;
+22 -10
View File
@@ -678,6 +678,8 @@ int Schedule_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
* @param object_instance [in] BACnet network port object instance number
* @param array_index [in] array index to write:
* 0=array size, 1 to N for individual array members
* @param array_size [in] The total number of elements in the array,
* if writing array size
* @param application_data [in] encoded element value
* @param application_data_len [in] The size of the encoded element value
* @return BACNET_ERROR_CODE value
@@ -685,6 +687,7 @@ int Schedule_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
static BACNET_ERROR_CODE Schedule_Weekly_Schedule_Element_Write(
uint32_t object_instance,
BACNET_ARRAY_INDEX array_index,
BACNET_UNSIGNED_INTEGER array_size,
uint8_t *application_data,
size_t application_data_len)
{
@@ -697,8 +700,11 @@ static BACNET_ERROR_CODE Schedule_Weekly_Schedule_Element_Write(
pObject = Schedule_Object(object_instance);
if (pObject) {
if (array_index == 0) {
/* This array is not required to be resizable
through BACnet write services */
(void)array_size;
error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else if (array_index <= BACNET_WEEKLY_SCHEDULE_SIZE) {
} else {
array_index--;
len = bacnet_dailyschedule_context_decode(
application_data, application_data_len, 0, &daily_schedule);
@@ -718,8 +724,6 @@ static BACNET_ERROR_CODE Schedule_Weekly_Schedule_Element_Write(
} else {
error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else {
error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
}
}
@@ -755,6 +759,8 @@ static int Schedule_Weekly_Schedule_Element_Length(
* @param object_instance [in] BACnet network port object instance number
* @param array_index [in] array index to write:
* 0=array size, 1 to N for individual array members
* @param array_size [in] The total number of elements in the array,
* if writing array size
* @param application_data [in] encoded element value
* @param application_data_len [in] The size of the encoded element value
* @return BACNET_ERROR_CODE value
@@ -762,6 +768,7 @@ static int Schedule_Weekly_Schedule_Element_Length(
static BACNET_ERROR_CODE Schedule_Exception_Schedule_Element_Write(
uint32_t object_instance,
BACNET_ARRAY_INDEX array_index,
BACNET_UNSIGNED_INTEGER array_size,
uint8_t *application_data,
size_t application_data_len)
{
@@ -773,8 +780,11 @@ static BACNET_ERROR_CODE Schedule_Exception_Schedule_Element_Write(
pObject = Schedule_Object(object_instance);
if (pObject) {
if (array_index == 0) {
/* This array is not required to be resizable
through BACnet write services */
(void)array_size;
error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else if (array_index <= BACNET_WEEKLY_SCHEDULE_SIZE) {
} else {
array_index--;
len = bacnet_special_event_decode(
application_data, application_data_len, &special_event);
@@ -785,8 +795,6 @@ static BACNET_ERROR_CODE Schedule_Exception_Schedule_Element_Write(
} else {
error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else {
error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
}
}
@@ -822,6 +830,8 @@ static int Schedule_Exception_Schedule_Element_Length(
* @param object_instance [in] BACnet network port object instance number
* @param array_index [in] array index to write:
* 0=array size, 1 to N for individual array members
* @param array_size [in] The total number of elements in the array,
* if writing array size
* @param application_data [in] encoded element value
* @param application_data_len [in] The size of the encoded element value
* @return BACNET_ERROR_CODE value
@@ -829,6 +839,7 @@ static int Schedule_Exception_Schedule_Element_Length(
static BACNET_ERROR_CODE Schedule_List_Of_Object_Property_References_Write(
uint32_t object_instance,
BACNET_ARRAY_INDEX array_index,
BACNET_UNSIGNED_INTEGER array_size,
uint8_t *application_data,
size_t application_data_len)
{
@@ -841,8 +852,11 @@ static BACNET_ERROR_CODE Schedule_List_Of_Object_Property_References_Write(
pObject = Schedule_Object(object_instance);
if (pObject) {
if (array_index == 0) {
error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
} else if (array_index <= BACNET_SCHEDULE_OBJ_PROP_REF_SIZE) {
/* This array is not required to be resizable
through BACnet write services */
(void)array_size;
error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else {
len = bacapp_decode_known_property(
application_data, application_data_len, &value, OBJECT_SCHEDULE,
PROP_LIST_OF_OBJECT_PROPERTY_REFERENCES);
@@ -864,8 +878,6 @@ static BACNET_ERROR_CODE Schedule_List_Of_Object_Property_References_Write(
} else {
error_code = ERROR_CODE_ABORT_OTHER;
}
} else {
error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
}
}
+7 -4
View File
@@ -1768,6 +1768,8 @@ static int Timer_State_Change_Value_Length(
* @param object_instance [in] BACnet object instance number
* @param array_index [in] array index to write:
* 0=array size, 1 to N for individual array members
* @param array_size [in] The total number of elements in the array,
* if writing array size
* @param application_data [in] encoded element value
* @param application_data_len [in] The size of the encoded element value
* @return BACNET_ERROR_CODE value
@@ -1775,6 +1777,7 @@ static int Timer_State_Change_Value_Length(
static BACNET_ERROR_CODE Timer_State_Change_Value_Write(
uint32_t object_instance,
BACNET_ARRAY_INDEX array_index,
BACNET_UNSIGNED_INTEGER array_size,
uint8_t *application_data,
size_t application_data_len)
{
@@ -1784,9 +1787,11 @@ static BACNET_ERROR_CODE Timer_State_Change_Value_Write(
bool status;
if (array_index == 0) {
/* fixed size array */
/* This array is not required to be resizable
through BACnet write services */
(void)array_size;
error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else if (array_index < TIMER_TRANSITION_MAX) {
} else {
len = bacnet_timer_value_decode(
application_data, application_data_len, &new_value);
if (len > 0) {
@@ -1801,8 +1806,6 @@ static BACNET_ERROR_CODE Timer_State_Change_Value_Write(
} else {
error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else {
error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
}
return error_code;
+4 -1
View File
@@ -2397,6 +2397,7 @@ static int Device_Configuration_File_Length(
* @param object_instance [in] BACnet object instance number
* @param array_index [in] array index to write:
* 0=array size, 1 to N for individual array members
* @param array_size [in] The total size of the array, if writing array size
* @param application_data [in] encoded element value
* @param application_data_len [in] The size of the encoded element value
* @return BACNET_ERROR_CODE value
@@ -2404,6 +2405,7 @@ static int Device_Configuration_File_Length(
static BACNET_ERROR_CODE Device_Configuration_File_Write(
uint32_t object_instance,
BACNET_ARRAY_INDEX array_index,
BACNET_UNSIGNED_INTEGER array_size,
uint8_t *application_data,
size_t application_data_len)
{
@@ -2415,7 +2417,8 @@ static BACNET_ERROR_CODE Device_Configuration_File_Write(
(void)object_instance;
if (array_index == 0) {
/* This array is not required to be resizable
through BACnet write services */
through BACnet write services */
(void)array_size;
error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else if (array_index <= BACNET_BACKUP_FILE_COUNT) {
len = bacnet_object_id_application_decode(