Skip to content

protocomm_console can write one byte past linebuf when input line exceeds LINE_BUF_SIZE (IDFGH-17695) #18638

@brabema

Description

@brabema

Answers checklist.

  • I have read the documentation ESP-IDF Programming Guide and the issue is not addressed there.
  • I have updated my IDF branch (master or release) to the latest version and checked that the issue is present there.
  • I have searched the issue tracker for a similar issue and not found a similar issue.

IDF version.

ESP-IDF v6.0.1

Espressif SoC revision.

ESP32-D0WDR2-V3

Operating System used.

Linux

How did you build your project?

Command line with idf.py

If you are using Windows, please specify command line type.

None

Development Kit.

Custom Board

Power Supply used.

External 3.3V

What is the expected behavior?

The code should check that the current write index is still within the bounds of linebuf before passing &linebuf[i] to uart_read_bytes().

If the input line exceeds LINE_BUF_SIZE, the console transport should handle it safely, for example by rejecting the overlong line, truncating it, or discarding input until the next line terminator.

No byte should be written outside the linebuf array, regardless of how many bytes are received before a newline.

What is the actual behavior?

The bounds check is performed after the destination pointer has already been passed to uart_read_bytes().

The current code has this pattern:

while (uart_read_bytes(uart_num, (uint8_t *) &linebuf[i], 1, 0) &&
       (i < LINE_BUF_SIZE)) {
    ...
}

### Steps to reproduce.

[protocomm_console_bounds_repro_steps_poc.zip](https://github.com/user-attachments/files/28100064/protocomm_console_bounds_repro_steps_poc.zip)

1. Extract the attached ZIP.

2. Run the host-side sanitizer reproducer:

   cd protocomm_console_bounds_repro
   make
   make run

   Expected result:

   ERROR: AddressSanitizer: stack-buffer-overflow

3. Build and flash the ESP32 repro app with ESP-IDF:

   cd protocomm_console_bounds_repro
   idf.py -C esp32_app -B build-hw set-target esp32 build
   idf.py -C esp32_app -B build-hw -p /dev/ttyUSB1 flash

4. After boot, trigger the visible UART repro:

   python3 tools/send_long_uart_line.py /dev/ttyUSB1 \
     --length 257 --delay-before-send 3 --read-seconds 10

   Do not keep idf.py monitor open at the same time, because the trigger script needs
the serial port.

5. Expected output:

   VISIBLE_REPRODUCED: guard changed 0x5a -> 0x41; i=256 reads=257

  This shows that the 257th input byte, 0x41 ('A'), was written immediately past the
  256-byte local buffer.

### Debug Logs.

```plain

Diagnostic report archive.

No response

More Information.

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions