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


The following commit(s) were added to refs/heads/master by this push:
     new 6cb6c459872 arch/xtensa/esp32: Fix buffer overflow in SPI poll exchange
6cb6c459872 is described below

commit 6cb6c45987253862035641896f87ad0ef52bd929
Author: Chip L. <[email protected]>
AuthorDate: Fri Feb 27 02:52:15 2026 +0800

    arch/xtensa/esp32: Fix buffer overflow in SPI poll exchange
    
    The esp32_spi_poll_exchange() function previously used a hardcoded
    length of sizeof(uint32_t) (4 bytes) for memcpy() operations and
    pointer increments, disregarding the actual remaining transfer_size.
    
    When an SPI transaction involved a data length not aligned to 4 bytes
    (such as a 1-byte payload commonly used in sub-GHz radio drivers),
    the driver forced a 4-byte memory transfer. This caused out-of-bounds
    reads and writes, leading to stack smashing and fatal CPU exceptions
    (e.g., EXCCAUSE=0000).
    
    This patch resolves the memory corruption vulnerability by:
    1. Calculating a precise `chunk` size for each iteration, strictly
       bounded by the remaining `transfer_size`.
    2. Limiting the memcpy() operations and the subsequent pointer
       increments (tp and rp) to this exact chunk size.
    3. Zero-initializing the temporary TX register (w_wd) before copying
       to clear padding and prevent reading uninitialized memory.
    4. Adding a NULL check for the receive pointer (rp) prior to the
       memcpy operation to prevent unintended memory writes.
    
    Signed-off-by: Chip L. <[email protected]>
---
 arch/xtensa/src/esp32/esp32_spi.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/arch/xtensa/src/esp32/esp32_spi.c 
b/arch/xtensa/src/esp32/esp32_spi.c
index d8931fd7b84..c64ac2d7be1 100644
--- a/arch/xtensa/src/esp32/esp32_spi.c
+++ b/arch/xtensa/src/esp32/esp32_spi.c
@@ -1104,12 +1104,19 @@ static void esp32_spi_poll_exchange(struct 
esp32_spi_priv_s *priv,
       for (int i = 0 ; i < transfer_size; i += sizeof(uint32_t))
         {
           uint32_t w_wd = UINT32_MAX;
+          uint32_t chunk = transfer_size - i;
+
+          if (chunk > sizeof(uint32_t))
+            {
+              chunk = sizeof(uint32_t);
+            }
 
           if (tp != NULL)
             {
-              memcpy(&w_wd, tp, sizeof(uint32_t));
+              w_wd = 0; /* Clear padding */
+              memcpy(&w_wd, tp, chunk);
 
-              tp += sizeof(uintptr_t);
+              tp += chunk;
             }
 
           putreg32(w_wd, data_buf_reg);
@@ -1160,13 +1167,22 @@ static void esp32_spi_poll_exchange(struct 
esp32_spi_priv_s *priv,
           for (int i = 0 ; i < transfer_size; i += sizeof(uint32_t))
             {
               uint32_t r_wd = getreg32(data_buf_reg);
+              uint32_t chunk = transfer_size - i;
+
+              if (chunk > sizeof(uint32_t))
+                {
+                  chunk = sizeof(uint32_t);
+                }
 
               spiinfo("recv=0x%" PRIx32 " data_reg=0x%" PRIxPTR "\n",
                       r_wd, data_buf_reg);
 
-              memcpy(rp, &r_wd, sizeof(uint32_t));
+              if (rp != NULL)
+                {
+                  memcpy(rp, &r_wd, chunk);
 
-              rp += sizeof(uintptr_t);
+                  rp += chunk;
+                }
 
               /* Update data_buf_reg to point to the next data buffer
                * register.

Reply via email to