FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Bugfix/buffer overflow in readpropm via malformed readpropertymultiple ack by skarg · Pull Request #1395 · bacnet-stack/bacnet-stack · GitHub

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .c  (2) .txt  (2) All 2 file types selected
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
44 changes: 27 additions & 17 deletions src/bacnet/basic/service/h_rpm_a.c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ int rpm_ack_decode_service_request(
int len = 0; /* number of bytes returned from decoding */
uint8_t tag_number = 0; /* decoded tag number */
int data_len = 0; /* data blob length */
int data_remaining = 0; /* bytes left in the current data blob */
int tag_len = 0; /* length of the tag portion of the data */
BACNET_READ_ACCESS_DATA *rpm_object;
BACNET_READ_ACCESS_DATA *old_rpm_object;
Expand Down Expand Up @@ -97,10 +98,17 @@ int rpm_ack_decode_service_request(
if (apdu_len &&
bacnet_is_opening_tag_number(apdu, apdu_len, 4, &tag_len)) {
data_len = bacnet_enclosed_data_length(apdu, apdu_len);
if (data_len < 0) {
debug_log_fprintf(
DEBUG_LOG_ERROR, stderr,
"RPM Ack: invalid enclosed property value length\n");
return BACNET_STATUS_ERROR;
}
/* propertyValue */
decoded_len += tag_len;
apdu_len -= tag_len;
apdu += tag_len;
data_remaining = data_len;
value = calloc(1, sizeof(BACNET_APPLICATION_DATA_VALUE));
rpm_property->value = value;
if (apdu_len &&
Expand All @@ -125,28 +133,30 @@ int rpm_ack_decode_service_request(
* OK. */
if (len < 0) {
/* problem decoding */
if (data_len >= 0) {
/* valid data that we'll skip over */
len = data_len;
bacapp_value_list_init(value, 1);
} else {
debug_log_fprintf(
DEBUG_LOG_ERROR, stderr,
"RPM Ack: unable to decode! %s:%s\n",
bactext_object_type_name(
rpm_object->object_type),
bactext_property_name(
rpm_property->propertyIdentifier));
/* note: caller will free the memory */
return BACNET_STATUS_ERROR;
}
len = data_remaining;
bacapp_value_list_init(value, 1);
}
if (len > data_remaining) {
debug_log_fprintf(
DEBUG_LOG_ERROR, stderr,
"RPM Ack: decoded length exceeds property "
"value length\n");
return BACNET_STATUS_ERROR;
}
decoded_len += len;
apdu_len -= len;
apdu += len;
if (apdu_len &&
data_remaining -= len;
if ((apdu_len < 0) || (data_remaining < 0)) {
debug_log_fprintf(
DEBUG_LOG_ERROR, stderr,
"RPM Ack: invalid remaining length while "
"decoding property value\n");
return BACNET_STATUS_ERROR;
}
if (apdu_len > 0 &&
bacnet_is_closing_tag_number(
apdu, apdu_len, 4, &tag_len)) {
apdu, (unsigned)apdu_len, 4, &tag_len)) {
decoded_len += tag_len;
apdu_len -= tag_len;
apdu += tag_len;
Expand Down
1 change: 1 addition & 0 deletions test/CMakeLists.txt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ list(APPEND testdirs
bacnet/basic/service/h_arf
bacnet/basic/service/h_awf
bacnet/basic/service/h_cov
bacnet/basic/service/h_rpm_a
bacnet/basic/service/h_rr
# basic/server
bacnet/basic/server/bacnet_device
Expand Down
79 changes: 79 additions & 0 deletions test/bacnet/basic/service/h_rpm_a/CMakeLists.txt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# SPDX-License-Identifier: MIT

cmake_minimum_required(VERSION 3.10 FATAL_ERROR)

get_filename_component(basename ${CMAKE_CURRENT_SOURCE_DIR} NAME)
project(test_${basename}
VERSION 1.0.0
LANGUAGES C)

string(REGEX REPLACE
"/test/bacnet/[a-zA-Z0-9_/-]*$"
"/src"
SRC_DIR
${CMAKE_CURRENT_SOURCE_DIR})
string(REGEX REPLACE
"/test/bacnet/[a-zA-Z0-9_/-]*$"
"/test"
TST_DIR
${CMAKE_CURRENT_SOURCE_DIR})

set(ZTST_DIR "${TST_DIR}/ztest/src")

add_compile_definitions(
BACNET_BIG_ENDIAN=0
CONFIG_ZTEST=1
BACDL_NONE=1
BACAPP_ALL
)

include_directories(
${SRC_DIR}
${TST_DIR}/ztest/include
)

add_executable(${PROJECT_NAME}
# File(s) under test
${SRC_DIR}/bacnet/basic/service/h_rpm_a.c
# Support files and stubs (pathname alphabetical)
${SRC_DIR}/bacnet/access_rule.c
${SRC_DIR}/bacnet/authentication_factor.c
${SRC_DIR}/bacnet/authentication_factor_format.c
${SRC_DIR}/bacnet/bacaction.c
${SRC_DIR}/bacnet/bacaddr.c
${SRC_DIR}/bacnet/bacapp.c
${SRC_DIR}/bacnet/bacdcode.c
${SRC_DIR}/bacnet/bacdest.c
${SRC_DIR}/bacnet/bacdevobjpropref.c
${SRC_DIR}/bacnet/abort.c
${SRC_DIR}/bacnet/bacerror.c
${SRC_DIR}/bacnet/reject.c
${SRC_DIR}/bacnet/bacint.c
${SRC_DIR}/bacnet/baclog.c
${SRC_DIR}/bacnet/bacreal.c
${SRC_DIR}/bacnet/bacstr.c
${SRC_DIR}/bacnet/bactext.c
${SRC_DIR}/bacnet/basic/sys/bigend.c
${SRC_DIR}/bacnet/basic/sys/debug.c
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/memcopy.c
${SRC_DIR}/bacnet/weeklyschedule.c
${SRC_DIR}/bacnet/bactimevalue.c
${SRC_DIR}/bacnet/dailyschedule.c
${SRC_DIR}/bacnet/calendar_entry.c
${SRC_DIR}/bacnet/special_event.c
${SRC_DIR}/bacnet/channel_value.c
${SRC_DIR}/bacnet/secure_connect.c
${SRC_DIR}/bacnet/rpm.c
# Test and test library files
./src/main.c
${ZTST_DIR}/ztest_mock.c
${ZTST_DIR}/ztest.c
)
74 changes: 74 additions & 0 deletions test/bacnet/basic/service/h_rpm_a/src/main.c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* @file
* @brief Unit tests for handler_read_property_multiple_ack decoder paths
* @copyright SPDX-License-Identifier: MIT
*/
#include <stdlib.h>
#include <string.h>
#include <zephyr/ztest.h>
#include <bacnet/bacdcode.h>
#include <bacnet/rpm.h>
#include <bacnet/basic/service/h_rpm_a.h>

#if defined(CONFIG_ZTEST_NEW_API)
ZTEST(h_rpm_a_tests, testMalformedTag4PayloadReturnsError)
#else
static void testMalformedTag4PayloadReturnsError(void)
#endif
{
uint8_t service_request[480] = { 0 };
uint8_t value_buffer[16] = { 0 };
BACNET_RPM_DATA rpmdata = { 0 };
BACNET_READ_ACCESS_DATA *read_access_data = NULL;
int len = 0;
int value_len = 0;
int test_len = 0;

rpmdata.object_type = OBJECT_DEVICE;
rpmdata.object_instance = 123;
len += rpm_ack_encode_apdu_object_begin(&service_request[len], &rpmdata);
len += rpm_ack_encode_apdu_object_property(
&service_request[len], PROP_OBJECT_LIST, BACNET_ARRAY_ALL);

len += encode_opening_tag(&service_request[len], 4);

value_len = encode_application_object_id(
&value_buffer[0], OBJECT_DEVICE, rpmdata.object_instance);
zassert_true(value_len > 0, NULL);
memcpy(&service_request[len], &value_buffer[0], (size_t)value_len);
len += value_len;

/* Truncated second value in same tag-4 payload to force partial decode. */
value_len = encode_application_real(&value_buffer[0], 1.0f);
zassert_true(value_len >= 5, NULL);
memcpy(&service_request[len], &value_buffer[0], 2);
len += 2;

len += encode_closing_tag(&service_request[len], 4);
len += rpm_ack_encode_apdu_object_end(&service_request[len]);

read_access_data = calloc(1, sizeof(BACNET_READ_ACCESS_DATA));
zassert_not_null(read_access_data, NULL);

test_len =
rpm_ack_decode_service_request(service_request, len, read_access_data);
zassert_equal(
test_len, BACNET_STATUS_ERROR,
"rpm_ack_decode_service_request returned %d, expected %d", test_len,
BACNET_STATUS_ERROR);

while (read_access_data) {
read_access_data = rpm_data_free(read_access_data);
}
}

#if defined(CONFIG_ZTEST_NEW_API)
ZTEST_SUITE(h_rpm_a_tests, NULL, NULL, NULL, NULL, NULL);
#else
void test_main(void)
{
ztest_test_suite(
h_rpm_a_tests, ztest_unit_test(testMalformedTag4PayloadReturnsError));
ztest_run_test_suite(h_rpm_a_tests);
}
#endif
Loading

Back | FazBrowse Home | New Git URL