Fixed dlmstp ringbuffer initialization corruption (#865)

* Added ringbuf API for testing.

* Fixed basic ms/tp datalink packet ringbuffer initialization buffer overrun.

* Added basic ms/tp datalink unit test

* Added Ringbuf_Initialize() API with buffer size checking.

* Changed examples to use Ringbuf_Initialize() API for buffer size checking.
This commit is contained in:
Steve Karg
2024-12-02 07:32:57 -06:00
committed by GitHub
parent f28b03bf81
commit 001b69cbd8
11 changed files with 526 additions and 14 deletions
+3 -2
View File
@@ -896,9 +896,10 @@ uint16_t bacnet_read_write_vendor_id_filter(void)
*/
void bacnet_read_write_init(void)
{
Ringbuf_Init(
Ringbuf_Initialize(
&Target_Data_Queue, (uint8_t *)&Target_Data_Buffer,
TARGET_DATA_QUEUE_SIZE, TARGET_DATA_QUEUE_COUNT);
sizeof(Target_Data_Buffer), TARGET_DATA_QUEUE_SIZE,
TARGET_DATA_QUEUE_COUNT);
/* handle i-am to support binding to other devices */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, My_I_Am_Bind);
/* handle the data coming back from confirmed requests */
+44 -1
View File
@@ -374,6 +374,23 @@ bool Ringbuf_Data_Put(RING_BUFFER *b, const volatile uint8_t *data_element)
return status;
}
/**
* Gets the data size of each element in the ring buffer
*
* @param b - pointer to RING_BUFFER structure
* @return size of each element in the ring buffer
*/
unsigned Ringbuf_Data_Size(RING_BUFFER const *b)
{
unsigned size = 0;
if (b) {
size = b->element_size;
}
return size;
}
/**
* Test that the parameter is a power of two.
*
@@ -395,8 +412,8 @@ static bool isPowerOfTwo(unsigned int x)
* @param buffer - pointer to a data buffer that is used to store the ring data
* @param element_size - size of one element in the data block
* @param element_count - number elements in the data block
*
* @return true if ring buffer was initialized
* @deprecated Use Ringbuf_Initialize() instead
*/
bool Ringbuf_Init(
RING_BUFFER *b,
@@ -419,3 +436,29 @@ bool Ringbuf_Init(
return status;
}
/**
* Configures the ring buffer data buffer. Note that the element_count
* parameter must be a power of two.
*
* @param b - pointer to RING_BUFFER structure
* @param buffer - pointer to a data buffer that is used to store the ring data
* @param buffer_size - size of the data buffer
* @param element_size - size of one element in the data block
* @param element_count - number elements in the data block
*
* @return true if ring buffer was initialized
*/
bool Ringbuf_Initialize(
RING_BUFFER *b,
volatile uint8_t *buffer,
unsigned buffer_size,
unsigned element_size,
unsigned element_count)
{
if ((element_size * element_count) <= buffer_size) {
return Ringbuf_Init(b, buffer, element_size, element_count);
}
return false;
}
+9
View File
@@ -89,6 +89,8 @@ volatile void *
Ringbuf_Peek_Next(RING_BUFFER const *b, const uint8_t *data_element);
BACNET_STACK_EXPORT
bool Ringbuf_Data_Put(RING_BUFFER *b, const volatile uint8_t *data_element);
BACNET_STACK_EXPORT
unsigned Ringbuf_Data_Size(RING_BUFFER const *b);
/* Note: element_count must be a power of two */
BACNET_STACK_EXPORT
bool Ringbuf_Init(
@@ -96,6 +98,13 @@ bool Ringbuf_Init(
volatile uint8_t *buffer,
unsigned element_size,
unsigned element_count);
BACNET_STACK_EXPORT
bool Ringbuf_Initialize(
RING_BUFFER *b,
volatile uint8_t *buffer,
unsigned buffer_size,
unsigned element_size,
unsigned element_count);
#ifdef __cplusplus
}
+6 -2
View File
@@ -92,6 +92,7 @@ uint16_t MSTP_Get_Send(struct mstp_port_struct_t *mstp_port, unsigned timeout)
struct dlmstp_packet *pkt;
struct dlmstp_user_data_t *user;
(void)timeout;
if (!mstp_port) {
return 0;
}
@@ -250,6 +251,7 @@ uint16_t MSTP_Get_Reply(struct mstp_port_struct_t *mstp_port, unsigned timeout)
struct dlmstp_user_data_t *user = NULL;
struct dlmstp_packet *pkt;
(void)timeout;
if (!mstp_port) {
return 0;
}
@@ -346,6 +348,7 @@ uint16_t dlmstp_receive(
uint16_t i;
uint32_t milliseconds;
(void)timeout;
if (!MSTP_Port) {
return 0;
}
@@ -993,9 +996,10 @@ bool dlmstp_init(char *ifname)
MSTP_Port->SilenceTimerReset = dlmstp_silence_reset;
user = (struct dlmstp_user_data_t *)MSTP_Port->UserData;
if (user && !user->Initialized) {
Ringbuf_Init(
Ringbuf_Initialize(
&user->PDU_Queue, (volatile uint8_t *)user->PDU_Buffer,
sizeof(user->PDU_Buffer), DLMSTP_MAX_INFO_FRAMES);
sizeof(user->PDU_Buffer), sizeof(struct dlmstp_packet),
DLMSTP_MAX_INFO_FRAMES);
MSTP_Init(MSTP_Port);
user->Initialized = true;
}