Add initialization and unpacking functions for BACnet Character String buffer decoder. (#1242)

This commit is contained in:
Steve Karg
2026-02-24 21:15:29 -06:00
committed by GitHub
parent 578f507125
commit e11cd319da
5 changed files with 103 additions and 12 deletions
+3 -1
View File
@@ -12,7 +12,7 @@ The git repositories are hosted at the following sites:
* https://bacnet.sourceforge.net/
* https://github.com/bacnet-stack/bacnet-stack/
## [Unreleased] - 2026-02-19
## [Unreleased] - 2026-02-23
### Security
@@ -41,6 +41,8 @@ The git repositories are hosted at the following sites:
### Added
* Add initialization and unpacking functions for BACnet Character
String buffer structure. (#1242)
* Add Host-N-Port minimal encode and decode which utilizes the octet
string and character string buffer encode and decode. (#1239)
* Added API for extending the basic Device object and children with
+59
View File
@@ -3456,6 +3456,65 @@ int bacnet_character_string_buffer_context_decode(
return apdu_len;
}
/**
* @brief Initializes a BACnet Character String buffer value
*
* @param value - the BACnet Character String buffer value to be initialized
* @param encoding - pointer to the BACnet Character String encoding value
* @param buffer - pointer to the buffer to hold the string value
* @param buffer_length - pointer to hold the buffer length
* @param buffer_size - size of the buffer in bytes
*/
void bacnet_character_string_buffer_init(
BACNET_CHARACTER_STRING_BUFFER *value,
uint8_t encoding,
char *buffer,
size_t buffer_size)
{
if (value) {
value->encoding = encoding;
value->buffer = buffer;
value->buffer_size = buffer_size;
value->buffer_length = 0;
}
}
/**
* @brief Unpacks a BACnet Character String buffer value from bytes
*
* @param value - the BACnet Character String buffer value to be unpacked
* @param encoding - pointer to the BACnet Character String encoding value
* @param buffer - pointer to the buffer to hold the string value
* @param buffer_length - pointer to hold the buffer length
*
* @return true if unpacked successfully, false if errors occur
*/
bool bacnet_character_string_buffer_unpack(
const BACNET_CHARACTER_STRING_BUFFER *value,
uint8_t *encoding,
char *buffer,
uint32_t *buffer_length)
{
if (value) {
if (value->buffer_length > value->buffer_size) {
/* fail if buffer length is greater than buffer size */
return false;
}
if (encoding) {
*encoding = value->encoding;
}
if (buffer_length) {
*buffer_length = value->buffer_length;
}
if (buffer && value->buffer && value->buffer_length) {
memcpy(buffer, value->buffer, value->buffer_length);
}
return true;
}
return false;
}
/**
* @brief Decodes from bytes into a BACnet Unsigned value
* from clause 20.2.4 Encoding of an Unsigned Integer Value
+12
View File
@@ -524,6 +524,18 @@ int bacnet_character_string_buffer_context_decode(
uint32_t apdu_size,
uint8_t tag_value,
BACNET_CHARACTER_STRING_BUFFER *value);
BACNET_STACK_EXPORT
void bacnet_character_string_buffer_init(
BACNET_CHARACTER_STRING_BUFFER *value,
uint8_t encoding,
char *buffer,
size_t buffer_size);
BACNET_STACK_EXPORT
bool bacnet_character_string_buffer_unpack(
const BACNET_CHARACTER_STRING_BUFFER *value,
uint8_t *encoding,
char *buffer,
uint32_t *buffer_length);
BACNET_STACK_EXPORT
int encode_bacnet_character_string(
+10 -6
View File
@@ -457,9 +457,11 @@ int host_n_port_minimal_address_decode(
{
int apdu_len = 0, len = 0;
uint8_t *buffer = NULL;
uint32_t buffer_length = 0;
size_t buffer_size = 0;
BACNET_TAG tag = { 0 };
BACNET_CHARACTER_STRING_BUFFER char_string = { 0 };
bool status = false;
/* default reject code */
if (error_code) {
@@ -507,10 +509,9 @@ int host_n_port_minimal_address_decode(
} else if (tag.context && (tag.number == 2)) {
if (address) {
address->tag = BACNET_HOST_ADDRESS_TAG_NAME;
char_string.buffer = address->host.name.fqdn;
char_string.buffer_size = sizeof(address->host.name.fqdn);
char_string.encoding = CHARACTER_ANSI_X34;
char_string.buffer_length = 0;
bacnet_character_string_buffer_init(
&char_string, CHARACTER_ANSI_X34, address->host.name.fqdn,
sizeof(address->host.name.fqdn));
}
len = bacnet_character_string_buffer_decode(
&apdu[apdu_len], apdu_size - apdu_len, tag.len_value_type,
@@ -522,13 +523,16 @@ int host_n_port_minimal_address_decode(
return BACNET_STATUS_REJECT;
}
if (address) {
if (char_string.buffer_length > char_string.buffer_size) {
status = bacnet_character_string_buffer_unpack(
&char_string, NULL, NULL, &buffer_length);
if (status) {
address->host.name.length = buffer_length;
} else {
if (error_code) {
*error_code = ERROR_CODE_REJECT_BUFFER_OVERFLOW;
}
return BACNET_STATUS_REJECT;
}
address->host.name.length = char_string.buffer_length;
}
apdu_len += len;
} else {
+19 -5
View File
@@ -2415,17 +2415,19 @@ static void test_bacnet_character_string_buffer(void)
{
uint8_t apdu[50] = { 0 };
char buffer[26] = { 0 }, test_buffer[26] = { 0 };
char unpack_buffer[26] = { 0 };
BACNET_CHARACTER_STRING_BUFFER value = { 0 }, test_value = { 0 };
int apdu_len = 0, null_len = 0, test_len = 0;
uint8_t tag_number = 0;
uint8_t unpack_encoding = 0;
uint32_t unpack_buffer_length = 0;
unsigned i;
int diff = 0; /* for memcmp */
value.buffer = buffer;
value.buffer_size = sizeof(buffer);
value.encoding = CHARACTER_ANSI_X34;
test_value.buffer = test_buffer;
test_value.buffer_size = sizeof(test_buffer);
bacnet_character_string_buffer_init(
&value, CHARACTER_ANSI_X34, buffer, sizeof(buffer));
bacnet_character_string_buffer_init(
&test_value, CHARACTER_ANSI_X34, test_buffer, sizeof(test_buffer));
apdu_len = encode_application_character_string_buffer(apdu, &value);
null_len = encode_application_character_string_buffer(NULL, &value);
zassert_equal(apdu_len, null_len, NULL);
@@ -2450,6 +2452,12 @@ static void test_bacnet_character_string_buffer(void)
zassert_equal(diff, 0, NULL);
zassert_equal(value.buffer_length, test_value.buffer_length, NULL);
zassert_equal(value.encoding, test_value.encoding, NULL);
bacnet_character_string_buffer_unpack(
&value, &unpack_encoding, unpack_buffer, &unpack_buffer_length);
zassert_equal(value.buffer_length, unpack_buffer_length, NULL);
zassert_equal(value.encoding, unpack_encoding, NULL);
diff = memcmp(buffer, unpack_buffer, value.buffer_length);
zassert_equal(diff, 0, NULL);
/* context tagged */
tag_number = i;
apdu_len = bacnet_character_string_buffer_context_encode(
@@ -2469,6 +2477,12 @@ static void test_bacnet_character_string_buffer(void)
zassert_equal(diff, 0, NULL);
zassert_equal(value.buffer_length, test_value.buffer_length, NULL);
zassert_equal(value.encoding, test_value.encoding, NULL);
bacnet_character_string_buffer_unpack(
&value, &unpack_encoding, unpack_buffer, &unpack_buffer_length);
zassert_equal(value.buffer_length, unpack_buffer_length, NULL);
zassert_equal(value.encoding, unpack_encoding, NULL);
diff = memcmp(buffer, unpack_buffer, value.buffer_length);
zassert_equal(diff, 0, NULL);
}
}