Checklist
Related issue: #1501
Issue #1501 appears to fix a leading-CRLF OPTIONS parser/double-free path. The crash below looks different: a valid OPTIONS request delivered over TLS in two stream fragments causes sip_receive() to call strcasecmp(NULL, ...) on the second fragment.
Environment
- Audio development kit: none
- Audio kit version (for ESP32-LyraT/ESP32-LyraT-Mini/ESP32-S3-Korvo-2): n/a
- [Required] Module or chip used: ESP32-WROVER-E
- [Required] IDF version (run
git describe --tags in $IDF_PATH folder to find it):
- [Required] ADF version (run
git describe --tags in $ADF_PATH folder to find it):
v2.7-based tree pinned to commit 9cf556de500019bb79f3bb84c821fda37668c052
- Build system: idf.py
- [Required] Running log: attached below excerpted from monitor output; full log available
- Compiler version (run
xtensa-esp32-elf-gcc --version in your project folder to find it):
xtensa-esp-elf-gcc (crosstool-NG esp-13.2.0_20240530) 13.2.0
- Operating system: Linux
- (Windows only) Environment type: n/a
- Using an IDE?: Yes (VS Code dev container)
- Power supply: USB
Problem Description
We are using esp_rtc over SIP/TLS against Kamailio. The ESP32 crashes reproducibly when Kamailio sends an inbound OPTIONS keepalive and the SIP request arrives split across two TLS reads.
We added TLS adapter logging around the ADF media library boundary and captured the exact inbound signaling. The OPTIONS request is valid, but it is delivered as two stream fragments:
- first read contains the request line,
Via, and From
- second read contains
To, Call-ID, CSeq: 80 OPTIONS, and Content-Length: 0
Immediately after the second read, the ESP32 panics in ROM strcasecmp, called from sip_receive() inside esp_rtc_sip.c.
The crash strongly suggests that the parser is treating the second TLS fragment as if it were a fresh SIP message instead of a continuation of the previous one. Because the second fragment begins with To: rather than a request line, the parsed method pointer appears to be null, and sip_receive() ends up executing strcasecmp(NULL, ...).
This is different from issue #1501. That issue discusses leading \r\nOPTIONS and cleanup/double-free behavior. In this case, the inbound request is valid and the trigger is normal TCP/TLS stream fragmentation.
The OPTIONS requests are Kamailio usrloc keepalives, identified by:
From: <sip:server@kamailio.org>
Call-ID: ksrulka-...
CSeq: 80 OPTIONS
Expected Behavior
esp_rtc should correctly reassemble and parse SIP requests received over TLS/TCP even when they arrive across multiple reads. A valid fragmented inbound OPTIONS request should not crash the device.
Actual Behavior
The ESP32 panics with LoadProhibited in ROM strcasecmp immediately after receiving the second fragment of a valid inbound OPTIONS request over TLS.
Backtrace:
strcasecmp in ROM
sip_receive at /builds/adf/esp-adf-libs-source/esp_media_protocols/esp_rtc/esp_rtc_core/esp_rtc_sip/esp_rtc_sip.c:1977
_sip_task at /builds/adf/esp-adf-libs-source/esp_media_protocols/esp_rtc/esp_rtc_core/esp_rtc_sip/esp_rtc_sip.c:2003
Steps to Reproduce
- Run an ESP32 firmware using
esp_rtc over SIP/TLS.
- Register and place a call through Kamailio.
- Enable Kamailio
usrloc keepalives so it sends inbound OPTIONS requests to the registered TLS contact.
- Ensure the inbound
OPTIONS request is delivered across multiple TLS reads. This happens naturally in our setup and does not require malformed traffic.
- Observe that when the second fragment arrives, the device crashes in
sip_receive().
Notes:
Code to Reproduce This Issue
Project-specific SIP service wrapper around esp_rtc:
- custom firmware based on ESP-IDF + ESP-ADF 2.7
- SIP/TLS transport
esp_rtc_service_init() and normal call flow
The failure appears to be inside the prebuilt ADF SIP/media protocols library rather than in application code. If useful, I can provide a reduced repro project similar to the one attached in issue #1501.
Debug Logs
I (95568) sip_signal: TLS_READ fd=58 peer_port=5061 bytes=221
I (95568) sip_signal: TLS_READ payload=OPTIONS sip:user-id@192.168.x.x:port;transport=TLS SIP/2.0\r\nVia: SIP/2.0/TLS X.X.X.X:5061;branch=z9hG4bKx.REDACTED\r\nFrom: <sip:server@kamailio.org>;tag=uloc-REDACTED\r\n
I (95748) sip_signal: TLS_READ fd=58 peer_port=5061 bytes=116
I (95758) sip_signal: TLS_READ payload=To: <sip:user-id@kamailio.org>\r\nCall-ID: ksrulka-REDACTED\r\nCSeq: 80 OPTIONS\r\nContent-Length: 0\r\n\r\n
Guru Meditation Error: Core 0 panic'ed (LoadProhibited). Exception was unhandled.
PC : 0x400011da PS : 0x00060330 A0 : 0x8013ed03 A1 : 0x3f849fb0
--- 0x400011da: strcasecmp in ROM
A2 : 0x00000000
EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000000
Backtrace: 0x400011d7:0x3f849fb0 0x4013ed00:0x3f849fd0 0x40093a0e:0x3f84a030
--- 0x400011d7: strcasecmp in ROM
--- 0x4013ed00: sip_receive at /builds/adf/esp-adf-libs-source/esp_media_protocols/esp_rtc/esp_rtc_core/esp_rtc_sip/esp_rtc_sip.c:1977
--- (inlined by) _sip_task at /builds/adf/esp-adf-libs-source/esp_media_protocols/esp_rtc/esp_rtc_core/esp_rtc_sip/esp_rtc_sip.c:2003
--- 0x40093a0e: vPortTaskWrapper at /COMPONENT_FREERTOS_DIR/FreeRTOS-Kernel/portable/xtensa/port.c:139
Additional observations:
A2 == 0x00000000 at the strcasecmp call site, which is consistent with a null method pointer.
- The panic happens immediately after the second fragment of the
OPTIONS request arrives.
- This is over TLS, so multi-read delivery is expected and legal.
Notes
If useful, I can also provide the patched libesp_media_protocols.a currently in use
Checklist
Related issue: #1501
Issue #1501 appears to fix a leading-CRLF
OPTIONSparser/double-free path. The crash below looks different: a validOPTIONSrequest delivered over TLS in two stream fragments causessip_receive()to callstrcasecmp(NULL, ...)on the second fragment.Environment
git describe --tagsin $IDF_PATH folder to find it):v5.3.3git describe --tagsin $ADF_PATH folder to find it):v2.7-based tree pinned to commit9cf556de500019bb79f3bb84c821fda37668c052xtensa-esp32-elf-gcc --versionin your project folder to find it):xtensa-esp-elf-gcc (crosstool-NG esp-13.2.0_20240530) 13.2.0Problem Description
We are using
esp_rtcover SIP/TLS against Kamailio. The ESP32 crashes reproducibly when Kamailio sends an inboundOPTIONSkeepalive and the SIP request arrives split across two TLS reads.We added TLS adapter logging around the ADF media library boundary and captured the exact inbound signaling. The
OPTIONSrequest is valid, but it is delivered as two stream fragments:Via, andFromTo,Call-ID,CSeq: 80 OPTIONS, andContent-Length: 0Immediately after the second read, the ESP32 panics in ROM
strcasecmp, called fromsip_receive()insideesp_rtc_sip.c.The crash strongly suggests that the parser is treating the second TLS fragment as if it were a fresh SIP message instead of a continuation of the previous one. Because the second fragment begins with
To:rather than a request line, the parsed method pointer appears to be null, andsip_receive()ends up executingstrcasecmp(NULL, ...).This is different from issue #1501. That issue discusses leading
\r\nOPTIONSand cleanup/double-free behavior. In this case, the inbound request is valid and the trigger is normal TCP/TLS stream fragmentation.The
OPTIONSrequests are Kamailiousrlockeepalives, identified by:From: <sip:server@kamailio.org>Call-ID: ksrulka-...CSeq: 80 OPTIONSExpected Behavior
esp_rtcshould correctly reassemble and parse SIP requests received over TLS/TCP even when they arrive across multiple reads. A valid fragmented inboundOPTIONSrequest should not crash the device.Actual Behavior
The ESP32 panics with
LoadProhibitedin ROMstrcasecmpimmediately after receiving the second fragment of a valid inboundOPTIONSrequest over TLS.Backtrace:
strcasecmpin ROMsip_receiveat/builds/adf/esp-adf-libs-source/esp_media_protocols/esp_rtc/esp_rtc_core/esp_rtc_sip/esp_rtc_sip.c:1977_sip_taskat/builds/adf/esp-adf-libs-source/esp_media_protocols/esp_rtc/esp_rtc_core/esp_rtc_sip/esp_rtc_sip.c:2003Steps to Reproduce
esp_rtcover SIP/TLS.usrlockeepalives so it sends inboundOPTIONSrequests to the registered TLS contact.OPTIONSrequest is delivered across multiple TLS reads. This happens naturally in our setup and does not require malformed traffic.sip_receive().Notes:
libesp_media_protocols.aassociated with issue ESP RTC crashing due to heap corruption after several hours (AUD-6549) #1501, so this appears to be a separate bug.Code to Reproduce This Issue
Project-specific SIP service wrapper around
esp_rtc:esp_rtc_service_init()and normal call flowThe failure appears to be inside the prebuilt ADF SIP/media protocols library rather than in application code. If useful, I can provide a reduced repro project similar to the one attached in issue #1501.
Debug Logs
Additional observations:
A2 == 0x00000000at thestrcasecmpcall site, which is consistent with a null method pointer.OPTIONSrequest arrives.Notes
If useful, I can also provide the patched
libesp_media_protocols.acurrently in use