Skip to content

Commit a59f372

Browse files
authored
fix: resolve buffer overflow in COBS frame decoding and add unit test for tight buffer handling (bacnet-stack#1425)
1 parent 851d03a commit a59f372

2 files changed

Lines changed: 63 additions & 2 deletions

File tree

  • test/bacnet/datalink/mstp/src

src/bacnet/datalink/mstp.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -561,8 +561,8 @@ void MSTP_Receive_Frame_FSM(struct mstp_port_struct_t *mstp_port)
561561
(mstp_port->FrameType <= Nmax_COBS_type)) {
562562
mstp_port->DataLength = cobs_frame_decode(
563563
&mstp_port->InputBuffer[mstp_port->Index + 1],
564-
mstp_port->InputBufferSize, mstp_port->InputBuffer,
565-
mstp_port->Index + 1);
564+
mstp_port->InputBufferSize - (mstp_port->Index + 1),
565+
mstp_port->InputBuffer, mstp_port->Index + 1);
566566
if (mstp_port->DataLength > 0) {
567567
/* GoodCRC */
568568
if (mstp_port->receive_state ==

test/bacnet/datalink/mstp/src/main.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,66 @@ static void testMasterNodeFSM(void)
646646
/* FIXME: write a unit test for the Master Node State Machine */
647647
}
648648

649+
static void testReceiveNodeFSM_COBS_Decode_TightBuffer(void)
650+
{
651+
struct mstp_port_struct_t mstp_port = { 0 }; /* port data */
652+
uint8_t my_mac = 0x05; /* local MAC address */
653+
uint8_t frame[MAX_MPDU] = { 0 };
654+
uint8_t rx_tight[MAX_MPDU] = { 0 };
655+
uint8_t payload[64] = { 0 };
656+
unsigned len;
657+
unsigned cobs_len;
658+
unsigned tight_size;
659+
unsigned guard_start;
660+
unsigned i;
661+
662+
for (i = 0; i < sizeof(payload); i++) {
663+
payload[i] = (uint8_t)(i + 1);
664+
}
665+
/* Include zeros to force multiple COBS blocks and real decode writes. */
666+
payload[3] = 0;
667+
payload[17] = 0;
668+
669+
len = MSTP_Create_Frame(
670+
frame, sizeof(frame), FRAME_TYPE_BACNET_EXTENDED_DATA_EXPECTING_REPLY,
671+
my_mac, my_mac, payload, sizeof(payload));
672+
zassert_true(len > 0, NULL);
673+
674+
cobs_len = (((unsigned)frame[5]) << 8) | frame[6];
675+
cobs_len += 2;
676+
tight_size = cobs_len + 1;
677+
zassert_true(tight_size < sizeof(rx_tight), NULL);
678+
679+
mstp_port.InputBuffer = &rx_tight[0];
680+
mstp_port.InputBufferSize = tight_size;
681+
mstp_port.OutputBuffer = &TxBuffer[0];
682+
mstp_port.OutputBufferSize = sizeof(TxBuffer);
683+
mstp_port.SilenceTimer = Timer_Silence;
684+
mstp_port.SilenceTimerReset = Timer_Silence_Reset;
685+
mstp_port.This_Station = my_mac;
686+
mstp_port.Nmax_info_frames = 1;
687+
mstp_port.Nmax_master = 127;
688+
MSTP_Init(&mstp_port);
689+
690+
guard_start = tight_size;
691+
for (i = guard_start; i < (guard_start + 8); i++) {
692+
rx_tight[i] = 0xA5;
693+
}
694+
695+
Load_Input_Buffer(frame, len);
696+
for (i = 0; i < len; i++) {
697+
RS485_Check_UART_Data(&mstp_port);
698+
MSTP_Receive_Frame_FSM(&mstp_port);
699+
}
700+
701+
zassert_true(mstp_port.ReceivedInvalidFrame == true, NULL);
702+
zassert_true(mstp_port.ReceivedValidFrame == false, NULL);
703+
zassert_true(mstp_port.receive_state == MSTP_RECEIVE_STATE_IDLE, NULL);
704+
for (i = guard_start; i < (guard_start + 8); i++) {
705+
zassert_true(rx_tight[i] == 0xA5, NULL);
706+
}
707+
}
708+
649709
static void testSlaveNodeFSM(void)
650710
{
651711
struct mstp_port_struct_t MSTP_Port = { 0 }; /* port data */
@@ -1367,6 +1427,7 @@ void test_main(void)
13671427
{
13681428
ztest_test_suite(
13691429
crc_tests, ztest_unit_test(testReceiveNodeFSM),
1430+
ztest_unit_test(testReceiveNodeFSM_COBS_Decode_TightBuffer),
13701431
ztest_unit_test(testMasterNodeFSM), ztest_unit_test(testSlaveNodeFSM),
13711432
ztest_unit_test(testZeroConfigNodeFSM),
13721433
ztest_unit_test(testAutoBaudNodeFSM));

0 commit comments

Comments
 (0)