Page 1 of 1

Suddenly getting a Heap error on SSCANF

Posted: Fri Apr 14, 2023 5:06 pm
by jim181
Hi all.
I've been developing a project for some time now, and all has been going smoothly, until yesterday when I am getting a heap error when calling SSCANF in my code (snippet attached below); There is another useage of the same code elsewhere with no issues.
I have run xPortGetFreeHeapSize() and I get normal heap free of 148996, with no drops, so I dont think this is a leak as such. If I comment out the SSCANF line, theres not a problem. Can anyone see an issue in this code?
Many many thanks, Jim
  1.         if(request->hasParam("value"))
  2.         {
  3.           String message;
  4.           message = request->getParam("value")->value();
  5.           //Serial.printf("Action %d. New Colour: %s\n",actionNum,message.c_str());
  6.  
  7.           uint8_t red, green, blue;
  8.           sscanf(message.c_str(),"%02X%02X%02X",&red,&green,&blue);
  9.           Serial.printf("RGB from msg %d/%d/%d\n",red, green,blue);  
This is the heap error:
assert failed: heap_caps_free heap_caps.c:339 (heap != NULL && "free() target pointer is outside heap areas")


Backtrace:0x40083a41:0x3ffd68100x4008be81:0x3ffd6830 0x40091401:0x3ffd6850 0x40083e9e:0x3ffd6980 0x40091431:0x3ffd69a0 0x400e4e26:0x3ffd69c0 0x400e4e35:0x3ffd69e0 0x400d8762:0x3ffd6a00 0x400d9b75:0x3ffd6a70 0x400e17ed:0x3ffd6a90 0x400df421:0x3ffd6ae0 0x400df531:0x3ffd6b30 0x400df719:0x3ffd6b80 0x4014efb9:0x3ffd6ba0 0x4014f031:0x3ffd6bd0 0x4014f7f2:0x3ffd6bf0

Re: Suddenly getting a Heap error on SSCANF

Posted: Sat Apr 15, 2023 11:11 am
by jim181
I've turned on thee exception decoder and this is the output. The sscanf seems to be working, but it fails immediately afterwards.
Not sure how to interpret this exception information - can anyone help? Many thanks.

RGB from msg 255/0/208

assert failed: heap_caps_free heap_caps.c:339 (heap != NULL && "free() target pointer is outside heap areas")


Backtrace:0x40083b0d:0x3ffd83e00x4008d30d:0x3ffd8400 0x4009288d:0x3ffd8420 0x40083f6a:0x3ffd8550 0x400928bd:0x3ffd8570 0x400e4f7e:0x3ffd8590 0x400e4f8d:0x3ffd85b0 0x400d88ae:0x3ffd85d0 0x400d9c59:0x3ffd8640 0x400e1919:0x3ffd8660 0x400df529:0x3ffd86b0 0x400df639:0x3ffd8700 0x400df821:0x3ffd8750 0x40169819:0x3ffd8770 0x40169891:0x3ffd87a0 0x4016a07a:0x3ffd87c0

#0 0x40083b0d:0x3ffd83e0 in panic_abort at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/esp_system/panic.c:402
#1 0x4008d30d:0x3ffd8400 in esp_system_abort at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/esp_system/esp_system.c:128
#2 0x4009288d:0x3ffd8420 in __assert_func at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/newlib/assert.c:85
#3 0x40083f6a:0x3ffd8550 in heap_caps_free at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/heap/heap_caps.c:339
(inlined by) heap_caps_free at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/heap/heap_caps.c:324
#4 0x400928bd:0x3ffd8570 in free at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/newlib/heap.c:39
#5 0x400e4f7e:0x3ffd8590 in String::invalidate() at C:/Users/Jim/.platformio/packages/framework-arduinoespressif32/cores/esp32/WString.cpp:175
#6 0x400e4f8d:0x3ffd85b0 in String::~String() at C:/Users/Jim/.platformio/packages/framework-arduinoespressif32/cores/esp32/WString.cpp:159
#7 0x400d88ae:0x3ffd85d0 in _ZZ5setupvENKUlP21AsyncWebServerRequestE18_clES0_$isra$349 at src/main.cpp:578
#8 0x400d9c59:0x3ffd8640 in std::_Function_handler<void (AsyncWebServerRequest*), setup()::{lambda(AsyncWebServerRequest*)#20}>::_M_invoke(std::_Any_data const&, AsyncWebServerRequest*&&) at c:\users\jim\.platformio\packages\toolchain-xtensa-esp32\xtensa-esp32-elf\include\c++\8.4.0\bits/std_function.h:297
#9 0x400e1919:0x3ffd8660 in std::function<void (AsyncWebServerRequest*)>::operator()(AsyncWebServerRequest*) const at c:\users\jim\.platformio\packages\toolchain-xtensa-esp32\xtensa-esp32-elf\include\c++\8.4.0\bits/std_function.h:687
(inlined by) AsyncCallbackWebHandler::handleRequest(AsyncWebServerRequest*) at .pio/libdeps/esp32doit-devkit-v1/ESPAsyncWebServer-esphome/src/WebHandlerImpl.h:132
#10 0x400df529:0x3ffd86b0 in AsyncWebServerRequest::_parseLine() at .pio/libdeps/esp32doit-devkit-v1/ESPAsyncWebServer-esphome/src/WebRequest.cpp:581 (discriminator 1)
#11 0x400df639:0x3ffd8700 in AsyncWebServerRequest::_onData(void*, unsigned int) at .pio/libdeps/esp32doit-devkit-v1/ESPAsyncWebServer-esphome/src/WebRequest.cpp:123
#12 0x400df821:0x3ffd8750 in std::_Function_handler<void (void*, AsyncClient*, void*, unsigned int), AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer*, AsyncClient*)::{lambda(void*, AsyncClient*, void*, unsigned int)#8}>::_M_invoke(std::_Any_data const&, void*&&, AsyncClient*&&, std::_Any_data const&, unsigned int&&) at .pio/libdeps/esp32doit-devkit-v1/ESPAsyncWebServer-esphome/src/WebRequest.cpp:76
(inlined by) _M_invoke at c:\users\jim\.platformio\packages\toolchain-xtensa-esp32\xtensa-esp32-elf\include\c++\8.4.0\bits/std_function.h:297
#13 0x40169819:0x3ffd8770 in std::function<void (void*, AsyncClient*, void*, unsigned int)>::operator()(void*, AsyncClient*, void*, unsigned int) const at c:\users\jim\.platformio\packages\toolchain-xtensa-esp32\xtensa-esp32-elf\include\c++\8.4.0\bits/std_function.h:687
(inlined by) AsyncClient::_recv(tcp_pcb*, pbuf*, signed char) at .pio/libdeps/esp32doit-devkit-v1/AsyncTCP-esphome/src/AsyncTCP.cpp:961
#14 0x40169891:0x3ffd87a0 in AsyncClient::_s_recv(void*, tcp_pcb*, pbuf*, signed char) at .pio/libdeps/esp32doit-devkit-v1/AsyncTCP-esphome/src/AsyncTCP.cpp:1253
#15 0x4016a07a:0x3ffd87c0 in _async_service_task(void*) at .pio/libdeps/esp32doit-devkit-v1/AsyncTCP-esphome/src/AsyncTCP.cpp:164
(inlined by) _async_service_task at .pio/libdeps/esp32doit-devkit-v1/AsyncTCP-esphome/src/AsyncTCP.cpp:199

Re: Suddenly getting a Heap error on SSCANF

Posted: Sat Apr 15, 2023 8:27 pm
by Craige Hales
I've not used sscanf in a long time. It seems likely, based on the %x doc in https://linux.die.net/man/3/sscanf,
Matches an unsigned hexadecimal integer; the next pointer must be a pointer to unsigned int
that the uint8 values are being used as uint32 and one of them, at least, is clobbering whatever is near it on the stack.

Code: Select all

uint8_t red, green, blue;
sscanf(message.c_str(),"%02X%02X%02X",&red,&green,&blue);
If it seems to work elsewhere, probably the local variables on the stack are laid out differently. With a little endian organization, writing to &red then green, then blue might seem to work, but three bytes beyond blue are being set to zero.

Re: Suddenly getting a Heap error on SSCANF

Posted: Mon Apr 17, 2023 1:45 am
by ESP_Sprite
Btw, just to confirm, this is memory corruption: your code somehow writes to a location it should not, corrupting the meta-information of the allocator.