Skip to content

Fix heap overflow in captive-portal 302 redirect#575

Open
maxim75 wants to merge 2 commits into
sle118:master-v4.3from
maxim75:fix-captive-portal-heap-overflow
Open

Fix heap overflow in captive-portal 302 redirect#575
maxim75 wants to merge 2 commits into
sle118:master-v4.3from
maxim75:fix-captive-portal-heap-overflow

Conversation

@maxim75

@maxim75 maxim75 commented Jul 11, 2026

Copy link
Copy Markdown

Summary

  • process_redirect() in components/wifi-manager/http_server_handlers.c allocated redirect_url one byte too small (no room for the trailing /) and passed the size of a different, larger buffer (buf_size) as the snprintf length limit instead of the actual allocation size (url_buf_size). This wrote past the end of the redirect_url heap block, corrupting the next block's tail guard.
  • Reproduced on real ESP32-S3 hardware: connecting a phone/laptop to the device's AP triggers a captive-portal probe (e.g. /hotspot-detect.html), which hits the 302-redirect path and crashes with CORRUPT HEAP: Bad tail / assert failed: multi_heap_free.
  • Fix: size url_buf_size to include the / and NUL, and pass that (not buf_size) to snprintf.

Test plan

  • Built firmware for esp32s3 (ESP-IDF v4.4.5, Docker) and flashed to a physical ESP32-S3-DevKitC-1 (N16R8) board
  • Confirmed clean boot to the recovery console before the fix, then reproduced the heap-corruption crash by connecting a client and letting it issue a captive-portal probe request
  • Applied the fix, rebuilt, reflashed, reproduced the same captive-portal request — no crash, clean 302 redirect

🤖 Generated with Claude Code

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>

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 */;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

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.

Comment thread INSTALL_HOW_TO.md Outdated
while time.time() - t0 < 15:
data = s.read(4096)
if data:
sys.stdout.buffer.write(data)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

Suggested change
sys.stdout.buffer.write(data)
sys.stdout.buffer.write(data)
sys.stdout.buffer.flush()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant