Crash when using String::move on empty string (original) (raw)

Board

ESP32-classic

Device Description

Not tried on several boards, but got it reproducible on ESP32-classic.

Hardware Configuration

Version

latest master (checkout manually)

IDE Name

PlatformIO

Operating System

Windows 11 / WSL2

Flash frequency

PSRAM enabled

yes

Upload speed

Description

Assigning an empty string using std::move may cause a crash.

So also assigning an empty string as result from a function will also eventually end up in crashes.

The fix is extremely simple; the memmove should only be called when rhs.len() > 0

Maybe the check should even be extended to if (rhs.len() && rhs.buffer())

void String::move(String &rhs) { if (buffer()) { if (capacity() >= rhs.len()) { if (rhs.len()) { // <<== This check added memmove(wbuffer(), rhs.buffer(), rhs.length() + 1); } setLen(rhs.len()); rhs.invalidate(); return; } else { if (!isSSO()) { free(wbuffer()); setBuffer(nullptr); } } } if (rhs.isSSO()) { setSSO(true); memmove(sso.buff, rhs.sso.buff, sizeof(sso.buff)); } else { setSSO(false); setBuffer(rhs.wbuffer()); } setCapacity(rhs.capacity()); setLen(rhs.len()); rhs.setSSO(false); rhs.setCapacity(0); rhs.setBuffer(nullptr); rhs.setLen(0); } #endif

N.B. it is a bit confusing that buffer() can return both a nullptr as well as a pointer when it is an empty string.
This might cause other issues as well as the rest of the coding-style in the class suggests it is more like checking for a non-empty string.

N.B.2. This bug is likely present for quite a long time, so maybe also needs backporting?

Sketch

N.B. I did not exactly test this sketch below, but it is a very stripped down gist of the code which is causing crashes in my project.

++ String foo() { return String(); }

// Important to note that the strings have to be constructed first // and then assigned a new value. String bar, working, crashing, crashing_too;

bar = foo(); working = bar; crashing = std::move(bar); crashing_too = foo();

Debug Message

Part of crash log, pointing clearly to `String::move`


Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.

Core  1 register dump:
PC      : 0x4008b05e  PS      : 0x00060730  A0      : 0x80160436  A1      : 0x3ffb1760  
A2      : 0x3ffb17d8  A3      : 0x00000000  A4      : 0x00000001  A5      : 0x3ffb1770  
A6      : 0x3ffb1760  A7      : 0x3ffb1770  A8      : 0x00000000  A9      : 0x00000000  
A10     : 0x3ffb1808  A11     : 0x00000001  A12     : 0x00000007  A13     : 0x3ffb1770  
A14     : 0x0000004e  A15     : 0x0000003f  SAR     : 0x00000010  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x00000000  LBEG    : 0x4008af4c  LEND    : 0x4008af62  LCOUNT  : 0xffffffff  


Backtrace: 0x4008b05b:0x3ffb1760 0x40160433:0x3ffb1780 0x40131e06:0x3ffb17a0 0x40101a5f:0x3ffb1890 0x4017312b:0x3ffb1ab0 0x40125bb5:0x3ffb1ad0 0x40157a4f:0x3ffb1c70 0x40152899:0x3ffb1e20 0x400d61fe:0x3ffb1e40 0x400e7d1e:0x3ffb1e60 0x400ecfe2:0x3ffb1e80 0x40137ca5:0x3ffb2000 0x4016a671:0x3ffb2040 0x40124ed5:0x3ffb2110 0x40162daf:0x3ffb2290
  #0  0x4008b05b in memmove at /builds/idf/crosstool-NG/.build/xtensa-esp-elf/src/newlib/newlib/libc/string/memmove.c:66
  #1  0x40160433 in String::move(String&) at ??:?
  #2  0x40131e06 in ESPEasy_TouchHandler::loadTouchObjects(EventStruct*) at ??:?
  #3  0x40101a5f in Plugin_123(unsigned char, EventStruct*, String&) at ??:?
  #4  0x4017312b in _Z21getDeviceIndex_sorted13deviceIndex_t$isra$0 at ??:?
  #5  0x40125bb5 in PluginCall(unsigned char, EventStruct*, String&) at ??:?
  #6  0x40157a4f in handle_devices() at :?
  #7  0x40152899 in UriGlob::canHandle(String const&, std::vector<String, std::allocator<String> >&) at :?
  #8  0x400d61fe in std::function<void ()>::operator()() const at .platformio/packages/toolchain-xtensa-esp-elf/xtensa-esp-elf/include/c++/13.2.0/bits/std_function.h:591
  #9  0x400e7d1e in FunctionRequestHandler::handle(WebServer&, http_method, String const&) at :?
  #10 0x400ecfe2 in WebServer::handleClient() at ??:?
  #11 0x40137ca5 in run10TimesPerSecond() at ??:?
  #12 0x4016a671 in _ZN17ESPEasy_Scheduler15handle_scheduleEv$constprop$0 at ??:?
  #13 0x40124ed5 in ESPEasy_loop() at ??:?
  #14 0x40162daf in app_main at ??:?

Other Steps to Reproduce

No response

I have checked existing issues, online documentation and the Troubleshooting Guide