This is an automated email from the ASF dual-hosted git repository. anchao pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit d5304d02fbe5850e25c456a40cc05b6788e9ce95 Author: wangyongrong <[email protected]> AuthorDate: Thu Oct 29 01:20:19 2026 +0800 rpmsg/port_uart: reject rx frame shorter than the port header hdr->len is parsed from the received byte stream, but the frame validation at the END delimiter never checks it against the minimum frame size: if (hdr->len != next || (hdr->crc != 0 && hdr->crc != rpmsg_port_uart_crc16(hdr))) A freshly fetched rx buffer is safe, because get_available_buffer() presets hdr->len to the queue length. The reachable path is buffer reuse: on a duplicate START the RECV_NORMAL branch resets state and next but keeps hdr, so returning to WAIT_START finds hdr != NULL and reuses the buffer without re-presetting hdr->len. By then hdr->len holds whatever the previous partial frame left at that offset - line data. A short frame only writes the first bytes of the header, so len (at offset 6) keeps that stale value. If an END arrives while the stale len happens to equal next (both 0, for instance), the first test passes and two things can go wrong depending on the stale crc: - crc == 0 short-circuits the second test, so the whole condition is false and the frame is queued as a valid one. Consumers that derive the payload size by subtracting the header size then underflow; the LZF path does exactly that, rxlen = hdr->len - sizeof(*hdr). This does not depend on CONFIG_RPMSG_PORT_UART_CRC: with the CRC compiled out the macro is a literal 0, so a non-zero stale crc compares equal to it and the frame is accepted just the same. - crc != 0 with the CRC compiled in evaluates crc16xor(&hdr->cmd, hdr->len - sizeof(hdr->crc)), and 0 - 2 underflows the size_t length argument, so crc16xor() walks far past the buffer. Reject len < sizeof(*hdr) as the first term of the condition. The short-circuit then keeps the CRC from being computed at all, and the frame is dropped and its buffer returned like any other malformed frame. A frame whose len equals sizeof(*hdr) carries no payload and stays valid. The port-spi driver already rejects such frames; port-uart did not. No upper bound is needed here: the copy loop only advances next while next < rxq->len, and the condition requires len == next. Signed-off-by: wangyongrong <[email protected]> --- drivers/rpmsg/rpmsg_port_uart.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/rpmsg/rpmsg_port_uart.c b/drivers/rpmsg/rpmsg_port_uart.c index d8fb5fa1601..a19bf749548 100644 --- a/drivers/rpmsg/rpmsg_port_uart.c +++ b/drivers/rpmsg/rpmsg_port_uart.c @@ -715,8 +715,9 @@ static void rpmsg_port_uart_rx_worker(FAR struct rpmsg_port_uart_s *rpuart, } else if (buf[i] == RPMSG_PORT_UART_END) { - if (hdr->len != next || (hdr->crc != 0 && - hdr->crc != rpmsg_port_uart_crc16(hdr))) + if (hdr->len < sizeof(*hdr) || hdr->len != next || + (hdr->crc != 0 && + hdr->crc != rpmsg_port_uart_crc16(hdr))) { rpmsgerr("Recv error crc=%u len=%u next=%u i=%zd " "dbg_i=%d\n", hdr->crc, hdr->len, next, i,
