From d33b221e17252362a9e93c35517529f6db0f0383 Mon Sep 17 00:00:00 2001 From: TD-er Date: Thu, 6 Feb 2025 11:43:33 +0100 Subject: [PATCH 1/3] Fix crash when using String::move on empty string (#10938) Fixes: #10938 --- cores/esp32/WString.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/cores/esp32/WString.cpp b/cores/esp32/WString.cpp index 71183213ac2..151880a0a21 100644 --- a/cores/esp32/WString.cpp +++ b/cores/esp32/WString.cpp @@ -238,16 +238,15 @@ String &String::copy(const char *cstr, unsigned int length) { #ifdef __GXX_EXPERIMENTAL_CXX0X__ void String::move(String &rhs) { if (buffer()) { - if (capacity() >= rhs.len()) { + if (capacity() >= rhs.len() && rhs.len() && rhs.buffer()) { memmove(wbuffer(), rhs.buffer(), rhs.length() + 1); setLen(rhs.len()); rhs.invalidate(); return; - } else { - if (!isSSO()) { - free(wbuffer()); - setBuffer(nullptr); - } + } + if (!isSSO()) { + free(wbuffer()); + setBuffer(nullptr); } } if (rhs.isSSO()) { @@ -259,10 +258,7 @@ void String::move(String &rhs) { } setCapacity(rhs.capacity()); setLen(rhs.len()); - rhs.setSSO(false); - rhs.setCapacity(0); - rhs.setBuffer(nullptr); - rhs.setLen(0); + rhs.init(); } #endif From 7948954cbc88829141b409e4825150d5ddc4b320 Mon Sep 17 00:00:00 2001 From: TD-er Date: Thu, 6 Feb 2025 12:00:56 +0100 Subject: [PATCH 2/3] Keep allocated memory when rhs fits Use case: Appending to a String with pre-allocated memory (e.g. from `reserve()`) --- cores/esp32/WString.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cores/esp32/WString.cpp b/cores/esp32/WString.cpp index 151880a0a21..a31cff5cf03 100644 --- a/cores/esp32/WString.cpp +++ b/cores/esp32/WString.cpp @@ -238,8 +238,12 @@ String &String::copy(const char *cstr, unsigned int length) { #ifdef __GXX_EXPERIMENTAL_CXX0X__ void String::move(String &rhs) { if (buffer()) { - if (capacity() >= rhs.len() && rhs.len() && rhs.buffer()) { - memmove(wbuffer(), rhs.buffer(), rhs.length() + 1); + if (capacity() >= rhs.len()) { + // Use case: When 'reserve()' was called and the first + // assignment/append is the return value of a function. + if (rhs.len() && rhs.buffer()) { + memmove(wbuffer(), rhs.buffer(), rhs.length() + 1); + } setLen(rhs.len()); rhs.invalidate(); return; From d024beab6412cfd78d0063f746d2c1ec70100a6c Mon Sep 17 00:00:00 2001 From: TD-er Date: Thu, 6 Feb 2025 14:02:58 +0100 Subject: [PATCH 3/3] No need to move 0-termination char in String::move --- cores/esp32/WString.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/esp32/WString.cpp b/cores/esp32/WString.cpp index a31cff5cf03..14b40e3ae34 100644 --- a/cores/esp32/WString.cpp +++ b/cores/esp32/WString.cpp @@ -242,7 +242,7 @@ void String::move(String &rhs) { // Use case: When 'reserve()' was called and the first // assignment/append is the return value of a function. if (rhs.len() && rhs.buffer()) { - memmove(wbuffer(), rhs.buffer(), rhs.length() + 1); + memmove(wbuffer(), rhs.buffer(), rhs.length()); } setLen(rhs.len()); rhs.invalidate();