diff --git a/CHANGELOG.md b/CHANGELOG.md index 884b1601..074df890 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,7 +24,7 @@ The git repositories are hosted at the following sites: Integrated the new types into the application data framework with application tag assignments. (#1163) * Added library specific string manipulation utilities including strcmp, - strncmp, and snprintf with offset functions. (#1163) + strncmp, and snprintf with offset functions. (#1163)(#1164) * Added default option to bactext name functions so that NULL can be returned when a name does not exist. (#1160) * Added library specific ltrim, rtrim, and trim string functions. (#1159) diff --git a/src/bacnet/bacstr.c b/src/bacnet/bacstr.c index ecc35918..2a2de1a1 100644 --- a/src/bacnet/bacstr.c +++ b/src/bacnet/bacstr.c @@ -2019,7 +2019,7 @@ char *bacnet_stptok(const char *s, char *tok, size_t toklen, const char *brk) /** * @brief General purpose print formatter snprintf() function with offset * @param buffer - destination string - * @param size - length of the destination string + * @param size - length of the destination string, or zero for length * @param offset - offset into the buffer to start the string * @param format - format string * @return total number of characters written from the beginning of buffer @@ -2027,19 +2027,35 @@ char *bacnet_stptok(const char *s, char *tok, size_t toklen, const char *brk) int bacnet_snprintf( char *buffer, size_t size, int offset, const char *format, ...) { - int length = 0; + int length = 0, write_length = 0; va_list args; + char *write_buffer = NULL; + size_t write_size = 0; + if (offset < 0) { + return offset; + } if (offset < size) { - size -= offset; + write_size = size - offset; if (buffer) { - buffer += offset; + write_buffer = buffer + offset; + } + } else if (size == 0) { + write_size = 0; + /* when size is zero, nothing is written to the buffer */ + } else { + return size; + } + va_start(args, format); + length = vsnprintf(write_buffer, write_size, format, args); + va_end(args); + write_length = offset + length; + if (size != 0) { + /* limit the return value to the size of the buffer */ + if (write_length > size) { + write_length = size; } - va_start(args, format); - length = vsnprintf(buffer, size, format, args); - va_end(args); - return offset + length; } - return size; + return write_length; } diff --git a/test/bacnet/bacdest/src/main.c b/test/bacnet/bacdest/src/main.c index 431bfd2c..404e8bc0 100644 --- a/test/bacnet/bacdest/src/main.c +++ b/test/bacnet/bacdest/src/main.c @@ -121,7 +121,7 @@ static void test_BACnetDestination_ASCII(void) zassert_true(len > 0, NULL); status = bacnet_destination_same(&destination, &test_destination); zassert_true(status, NULL); - /* get the length */ + /* get the length without NULL termination */ null_len = bacnet_destination_to_ascii(&test_destination, NULL, 0); if (null_len > 0) { test_ascii = calloc(null_len, sizeof(char)); @@ -132,7 +132,15 @@ static void test_BACnetDestination_ASCII(void) while (--test_len) { len = bacnet_destination_to_ascii( &test_destination, test_ascii, test_len); - zassert_equal(len, null_len, NULL); + if (test_len > 0) { + zassert_equal( + len, test_len, "%s len=%d test_len=%d", test_ascii, len, + test_len); + } else { + zassert_equal( + len, null_len, "%s len=%d null_len=%d", test_ascii, len, + null_len); + } } free(test_ascii); } diff --git a/test/bacnet/bacstr/src/main.c b/test/bacnet/bacstr/src/main.c index 8736fe4b..bf055a74 100644 --- a/test/bacnet/bacstr/src/main.c +++ b/test/bacnet/bacstr/src/main.c @@ -790,10 +790,27 @@ ZTEST(bacstr_tests, test_bacnet_snprintf) static void test_bacnet_snprintf(void) #endif { - int buf_len = 0, str_len; + int buf_len = 0, str_len, null_len = 0, test_null_len = 0; int i; char str[30] = ""; + const char *null_string = "REALLY BIG NULL STRING"; + const char *one_char_string = "1"; + const char *two_char_string = "12"; + /* one char */ + buf_len = 0; + str_len = 1; + buf_len = bacnet_snprintf(str, str_len, buf_len, "%s", one_char_string); + zassert_equal(buf_len, str_len, "buf_len=%d str_len=%d", buf_len, str_len); + /* two char */ + buf_len = 0; + str_len = 2; + buf_len = bacnet_snprintf(str, str_len, buf_len, "%s", two_char_string); + zassert_equal(buf_len, str_len, "buf_len=%d str_len=%d", buf_len, str_len); + buf_len = bacnet_snprintf(str, str_len, buf_len, "%s", two_char_string); + zassert_equal(buf_len, str_len, "buf_len=%d str_len=%d", buf_len, str_len); + /* large chars */ + buf_len = 0; str_len = sizeof(str); for (i = 0; i < 5; i++) { /* appending formatted strings */ @@ -801,10 +818,14 @@ static void test_bacnet_snprintf(void) buf_len = bacnet_snprintf(str, str_len, buf_len, "REALLY BIG STRING BASS"); buf_len = bacnet_snprintf(str, str_len, buf_len, "}"); + /* appending to a NULL string for length */ + null_len = bacnet_snprintf(NULL, 0, null_len, null_string); + test_null_len += strlen(null_string); } zassert_equal(buf_len, str_len, "buf_len=%d str_len=%d", buf_len, str_len); zassert_equal( str[buf_len - 1], 0, "str[%d]=%c", buf_len - 1, str[buf_len - 1]); + zassert_equal(null_len, test_null_len, "null_len=%d", null_len); } /**