This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 5e3a85a54a0cfb92d77729a7081400b6ca229261 Author: Marco Casaroli <[email protected]> AuthorDate: Mon Nov 2 10:12:28 2026 +0100 drivers/leds/ws2812: Bound the byte order transformation to the LED chain. With CONFIG_WS2812_COMPONENT_TRANSFORM, a device with a byte order transformation sends the data through byte_order_buffer, which holds WS2812_RW_PIXEL_SIZE * nleds bytes. ws2812_write() transformed the full request into this buffer, so a write past the end of the chain overflowed the buffer. The lower half limits the length only after this copy. ws2812_read() transformed the requested number of pixels also when the lower half returned fewer bytes or an error, so it copied memory after the buffer to the caller. Limit the length to the LEDs from the file position to the end of the chain before the transformation, as the lower halves do. In the read path, transform only the bytes that the lower half returned. The transformation came with the AVR DA/DB WS2812 driver (#21338). No in-tree lower half turns it on yet. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marco Casaroli <[email protected]> --- drivers/leds/ws2812.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/drivers/leds/ws2812.c b/drivers/leds/ws2812.c index 26c23de9001..beb7b26bb96 100644 --- a/drivers/leds/ws2812.c +++ b/drivers/leds/ws2812.c @@ -279,6 +279,42 @@ static void ws2812_byte_order_transform_rgb(FAR const char *src, } } +/**************************************************************************** + * Name: ws2812_byte_order_len + * + * Description: + * Limit a transfer through byte_order_buffer to the LEDs from the file + * position to the end of the chain, so that it fits in the buffer. + * + * Input Parameters: + * filep - Pointer system file data + * priv - The device + * len - Requested length in bytes + * + * Returned Value: + * The length in bytes to transfer. + * + ****************************************************************************/ + +static size_t ws2812_byte_order_len(FAR struct file *filep, + FAR struct ws2812_dev_s *priv, + size_t len) +{ + off_t size = (off_t)priv->nleds * WS2812_RW_PIXEL_SIZE; + + if (filep->f_pos >= size) + { + return 0; + } + + if (len > (size_t)(size - filep->f_pos)) + { + len = size - filep->f_pos; + } + + return len; +} + # endif /**************************************************************************** @@ -402,6 +438,7 @@ ssize_t ws2812_write(FAR struct file *filep, # ifdef CONFIG_WS2812_COMPONENT_TRANSFORM_RGB case WS2812_COMPONENT_TRANSFORM_RGB: { + len = ws2812_byte_order_len(filep, priv, len); ws2812_byte_order_transform_rgb( data, priv->byte_order_buffer, @@ -497,12 +534,16 @@ ssize_t ws2812_read(FAR struct file *filep, # ifdef CONFIG_WS2812_COMPONENT_TRANSFORM_RGB case WS2812_COMPONENT_TRANSFORM_RGB: { + len = ws2812_byte_order_len(filep, priv, len); res = priv->read(filep, priv->byte_order_buffer, len); - ws2812_byte_order_transform_rgb( - priv->byte_order_buffer, - data, - len >> 2 - ); + if (res > 0) + { + ws2812_byte_order_transform_rgb( + priv->byte_order_buffer, + data, + res >> 2 + ); + } } break; # endif /* CONFIG_WS2812_COMPONENT_TRANSFORM_RGB */
