Fix heap overflow in captive-portal 302 redirect#575
Conversation
process_redirect() allocated redirect_url one byte short (no room for the trailing '/' it writes) and then called snprintf() with buf_size (the size of the unrelated, larger `redirect` buffer) as the length limit instead of url_buf_size. This let snprintf write past the end of the redirect_url allocation, corrupting the next heap block's tail guard. Reproduced on real ESP32-S3 hardware: any client doing captive-portal detection (e.g. a phone/laptop requesting /hotspot-detect.html while connected to the device's AP) triggered the 302-redirect path and crashed the device with "CORRUPT HEAP: Bad tail" / assert in multi_heap_free. Also adds INSTALL_HOW_TO.md documenting the ESP32-S3 build/flash process, including the ESP-IDF version constraints (4.4+ needed for esp32s3 support, but must stay below 5.3 where this codebase's legacy I2S driver usage stops compiling) and the Quad-flash/Octal-PSRAM sdkconfig fix needed for common N16R8-style boards. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request introduces a detailed guide (INSTALL_HOW_TO.md) for building and flashing Squeezelite-ESP32 on ESP32-S3 boards and fixes a buffer size calculation and snprintf limit when handling HTTP 302 redirects in http_server_handlers.c. The review feedback highlights a missing NULL check on a memory allocation in http_server_handlers.c that could lead to a crash, and suggests adding an explicit flush to the Python boot verification script in the documentation to prevent buffered output from appearing hung.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
|
|
||
| if(strcasestr(status,"302")){ | ||
| size_t url_buf_size = strlen(location_prefix) + strlen(ap_ip_address)+1; | ||
| size_t url_buf_size = strlen(location_prefix) + strlen(ap_ip_address)+1 /* '/' */ +1 /* NUL */; |
There was a problem hiding this comment.
The allocation of redirect_url using malloc_init_external on the subsequent line (line 954) is not checked for NULL. If the allocation fails due to memory exhaustion, the subsequent memset and snprintf calls will dereference a null pointer and crash the device. Consider adding a NULL check for redirect_url before using it.
| while time.time() - t0 < 15: | ||
| data = s.read(4096) | ||
| if data: | ||
| sys.stdout.buffer.write(data) |
There was a problem hiding this comment.
In Python 3, sys.stdout (and its underlying buffer) is buffered by default when writing bytes. Without an explicit flush, the serial output may not be displayed in real-time, making the monitor script appear to hang. Adding sys.stdout.buffer.flush() ensures immediate display of the received data.
| sys.stdout.buffer.write(data) | |
| sys.stdout.buffer.write(data) | |
| sys.stdout.buffer.flush() |
Summary
process_redirect()incomponents/wifi-manager/http_server_handlers.callocatedredirect_urlone byte too small (no room for the trailing/) and passed the size of a different, larger buffer (buf_size) as thesnprintflength limit instead of the actual allocation size (url_buf_size). This wrote past the end of theredirect_urlheap block, corrupting the next block's tail guard./hotspot-detect.html), which hits the 302-redirect path and crashes withCORRUPT HEAP: Bad tail/assert failed: multi_heap_free.url_buf_sizeto include the/and NUL, and pass that (notbuf_size) tosnprintf.Test plan
🤖 Generated with Claude Code