Bugfix/deprecate decode tag number and value (#481)

* added or updated secure the BACnet primitive value decoders - the core codecs - named bacnet_x_decode(), bacnet_x_application_decode() and bacnet_x_context_decode where x is one of the 13 BACnet primitive value names.  The updated API includes an APDU size to prevent over-reading of an APDU buffer while decoding.  Improved or added unit test code coverage for the BACnet primitive value decoders.

* marked the insecure decoding API as 'deprecated' which is defined in src/bacnet/basic/sys/platform.h and can be disabled during a build. 

* added secure decoders for BACnetTimeValue, BACnetHostNPort, BACnetTimeStamp, BACnetAddress, and Weekly_Schedule and improved unit test code coverage.

* improved test code coverage for BACnet objects and properties.

* secured AtomicReadFile and AtomicWriteFile service decoders and improved unit test code coverage.

* secured BACnet Error service decoder and improved unit test code coverage.

---------

Co-authored-by: Steve Karg <skarg@users.sourceforge.net>
This commit is contained in:
Steve Karg
2023-09-08 11:39:27 -05:00
committed by GitHub
parent bc8c261153
commit f641aacddb
67 changed files with 6103 additions and 3145 deletions
+36 -37
View File
@@ -9,6 +9,7 @@
*/
#include <zephyr/ztest.h>
#include <bacnet/bacdef.h>
#include <bacnet/bacerror.h>
/**
@@ -16,31 +17,25 @@
* @{
*/
/**
* @brief decode the whole APDU - mainly used for unit testing
*/
static int bacerror_decode_apdu(uint8_t *apdu,
unsigned apdu_len,
unsigned apdu_size,
uint8_t *invoke_id,
BACNET_CONFIRMED_SERVICE *service,
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code)
{
int len = 0;
int apdu_len = BACNET_STATUS_ERROR;
if (!apdu)
return -1;
/* optional checking - most likely was already done prior to this call */
if (apdu_len) {
if (apdu[0] != PDU_TYPE_ERROR)
return -1;
if (apdu_len > 1) {
len = bacerror_decode_service_request(&apdu[1], apdu_len - 1,
invoke_id, service, error_class, error_code);
if (apdu && (apdu_size > 0)) {
if (apdu[0] != PDU_TYPE_ERROR) {
return BACNET_STATUS_ERROR;
}
apdu_len = 1;
apdu_len = bacerror_decode_service_request(&apdu[apdu_len],
apdu_size - apdu_len, invoke_id, service, error_class, error_code);
}
return len;
return apdu_len;
}
/**
@@ -53,8 +48,7 @@ static void testBACError(void)
#endif
{
uint8_t apdu[480] = { 0 };
int len = 0;
int apdu_len = 0;
int len = 0, apdu_len = 0, null_len, test_len;
uint8_t invoke_id = 0;
BACNET_CONFIRMED_SERVICE service = 0;
BACNET_ERROR_CLASS error_class = 0;
@@ -64,37 +58,44 @@ static void testBACError(void)
BACNET_ERROR_CLASS test_error_class = 0;
BACNET_ERROR_CODE test_error_code = 0;
len = bacerror_encode_apdu(
NULL, invoke_id, service, error_class, error_code);
zassert_equal(len, 0, NULL);
null_len =
bacerror_encode_apdu(NULL, invoke_id, service, error_class, error_code);
len = bacerror_encode_apdu(
&apdu[0], invoke_id, service, error_class, error_code);
zassert_equal(len, null_len, NULL);
zassert_not_equal(len, 0, NULL);
apdu_len = len;
null_len = bacerror_decode_apdu(&apdu[0], apdu_len, NULL, NULL, NULL, NULL);
len = bacerror_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_service, &test_error_class, &test_error_code);
zassert_not_equal(len, -1, NULL);
zassert_not_equal(len, BACNET_STATUS_ERROR, "len=%d", len);
zassert_equal(len, null_len, NULL);
zassert_equal(test_invoke_id, invoke_id, NULL);
zassert_equal(test_service, service, NULL);
zassert_equal(test_error_class, error_class, NULL);
zassert_equal(test_error_code, error_code, NULL);
/* test too short lengths */
while (len) {
len--;
test_len =
bacerror_decode_apdu(&apdu[0], len, &test_invoke_id,
&test_service, &test_error_class, &test_error_code);
zassert_equal(
test_len, BACNET_STATUS_ERROR, "len=%d test_len=%d", len, test_len);
}
/* change type to get negative response */
apdu[0] = PDU_TYPE_ABORT;
len = bacerror_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_service, &test_error_class, &test_error_code);
zassert_equal(len, -1, NULL);
zassert_true(len <= 0, NULL);
/* test NULL APDU */
len = bacerror_decode_apdu(NULL, apdu_len, &test_invoke_id, &test_service,
&test_error_class, &test_error_code);
zassert_equal(len, -1, NULL);
/* force a zero length */
len = bacerror_decode_apdu(&apdu[0], 0, &test_invoke_id, &test_service,
&test_error_class, &test_error_code);
zassert_equal(len, 0, NULL);
len = bacerror_decode_apdu(NULL, apdu_len, &test_invoke_id,
&test_service, &test_error_class, &test_error_code);
zassert_true(len <= 0, NULL);
/* check them all... */
for (service = 0; service < MAX_BACNET_CONFIRMED_SERVICE; service++) {
@@ -106,8 +107,9 @@ static void testBACError(void)
&apdu[0], invoke_id, service, error_class, error_code);
apdu_len = len;
zassert_not_equal(len, 0, NULL);
len = bacerror_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_service, &test_error_class, &test_error_code);
len = bacerror_decode_apdu(&apdu[0], apdu_len,
&test_invoke_id, &test_service, &test_error_class,
&test_error_code);
zassert_not_equal(len, -1, NULL);
zassert_equal(test_invoke_id, invoke_id, NULL);
zassert_equal(test_service, service, NULL);
@@ -127,7 +129,7 @@ static void testBACError(void)
zassert_not_equal(len, 0, NULL);
len = bacerror_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_service, &test_error_class, &test_error_code);
zassert_not_equal(len, -1, NULL);
zassert_not_equal(len, BACNET_STATUS_ERROR, NULL);
zassert_equal(test_invoke_id, invoke_id, NULL);
zassert_equal(test_service, service, NULL);
zassert_equal(test_error_class, error_class, NULL);
@@ -137,15 +139,12 @@ static void testBACError(void)
* @}
*/
#if defined(CONFIG_ZTEST_NEW_API)
ZTEST_SUITE(bacerror_tests, NULL, NULL, NULL, NULL, NULL);
#else
void test_main(void)
{
ztest_test_suite(bacerror_tests,
ztest_unit_test(testBACError)
);
ztest_test_suite(bacerror_tests, ztest_unit_test(testBACError));
ztest_run_test_suite(bacerror_tests);
}