From 1946bc4e44dd5ad0fa8e5cfb6f1cf429030a8009 Mon Sep 17 00:00:00 2001 From: dongjiuzhu1 Date: Fri, 29 Aug 2025 16:29:44 +0800 Subject: [PATCH] drivers/serial: fix crash when buffer is full and only recvbuf is implemented When the receive buffer is full and the driver only implements recvbuf operation without receive operation, the code would crash due to calling a NULL function pointer. This patch fixes the issue by: 1. Check if recvbuf is available before calling it 2. When buffer is full, use a temporary buffer to drain hardware FIFO to prevent data accumulation in hardware 3. Add proper NULL check for receive operation to avoid crash 4. Initialize pbuf to NULL to prevent uninitialized variable usage This ensures the serial driver works correctly even when only recvbuf is implemented and the receive buffer is full. Signed-off-by: dongjiuzhu1 --- drivers/serial/serial_io.c | 60 +++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/drivers/serial/serial_io.c b/drivers/serial/serial_io.c index c88875a1342..9518fc4e302 100644 --- a/drivers/serial/serial_io.c +++ b/drivers/serial/serial_io.c @@ -166,7 +166,7 @@ void uart_recvchars(FAR uart_dev_t *dev) { int nexthead = rxbuf->head + 1 < rxbuf->size ? rxbuf->head + 1 : 0; bool is_full = (nexthead == rxbuf->tail); - FAR char *pbuf; + FAR char *pbuf = NULL; char ch; #ifdef CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS @@ -217,38 +217,52 @@ void uart_recvchars(FAR uart_dev_t *dev) /* Get this next character from the hardware */ - if (!is_full && dev->ops->recvbuf) + if (dev->ops->recvbuf) { ssize_t ret; - if (rxbuf->tail > rxbuf->head) + if (!is_full) { - nbytes = rxbuf->tail - rxbuf->head - 1; - } - else if (rxbuf->tail) - { - nbytes = rxbuf->size - rxbuf->head; + if (rxbuf->tail > rxbuf->head) + { + nbytes = rxbuf->tail - rxbuf->head - 1; + } + else if (rxbuf->tail) + { + nbytes = rxbuf->size - rxbuf->head; + } + else + { + nbytes = rxbuf->size - rxbuf->head - 1; + } + + pbuf = &rxbuf->buffer[rxbuf->head]; + ret = uart_recvbuf(dev, pbuf, nbytes); + if (ret <= 0) + { + continue; + } + + nbytes = ret; + rxbuf->head += nbytes; + if (rxbuf->head >= rxbuf->size) + { + rxbuf->head = 0; + } } else { - nbytes = rxbuf->size - rxbuf->head - 1; - } + pbuf = &ch; + nbytes = 1; - pbuf = &rxbuf->buffer[rxbuf->head]; - ret = uart_recvbuf(dev, pbuf, nbytes); - if (ret <= 0) - { - continue; - } - - nbytes = ret; - rxbuf->head += nbytes; - if (rxbuf->head >= rxbuf->size) - { - rxbuf->head = 0; + ret = uart_recvbuf(dev, pbuf, nbytes); + if (ret <= 0) + { + continue; + } } } - else + else if(dev->ops->receive) { unsigned int status;