Skip to content

Commit 9712170

Browse files
Fix String.replace overlapping strcpy (#5966)
* Fix String.replace overlapping strcpy Fixes #5949 Adds a test from the issue above and fixes the problem valgrind found. Additional pathological memcpy->memmove fixes
1 parent 4b596d8 commit 9712170

File tree

2 files changed

+18
-6
lines changed

2 files changed

+18
-6
lines changed

cores/esp8266/WString.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ void String::move(String &rhs) {
237237
}
238238
if (rhs.sso()) {
239239
setSSO(true);
240-
memcpy(sso_buf, rhs.sso_buf, sizeof(sso_buf));
240+
memmove(sso_buf, rhs.sso_buf, sizeof(sso_buf));
241241
} else {
242242
setSSO(false);
243243
setBuffer(rhs.wbuffer());
@@ -730,21 +730,21 @@ void String::replace(const String& find, const String& replace) {
730730
char *foundAt;
731731
if(diff == 0) {
732732
while((foundAt = strstr(readFrom, find.buffer())) != NULL) {
733-
memcpy(foundAt, replace.buffer(), replace.len());
733+
memmove(foundAt, replace.buffer(), replace.len());
734734
readFrom = foundAt + replace.len();
735735
}
736736
} else if(diff < 0) {
737737
char *writeTo = wbuffer();
738738
while((foundAt = strstr(readFrom, find.buffer())) != NULL) {
739739
unsigned int n = foundAt - readFrom;
740-
memcpy(writeTo, readFrom, n);
740+
memmove(writeTo, readFrom, n);
741741
writeTo += n;
742-
memcpy(writeTo, replace.buffer(), replace.len());
742+
memmove(writeTo, replace.buffer(), replace.len());
743743
writeTo += replace.len();
744744
readFrom = foundAt + find.len();
745745
setLen(len() + diff);
746746
}
747-
strcpy(writeTo, readFrom);
747+
memmove(writeTo, readFrom, strlen(readFrom)+1);
748748
} else {
749749
unsigned int size = len(); // compute size needed for result
750750
while((foundAt = strstr(readFrom, find.buffer())) != NULL) {
@@ -760,7 +760,7 @@ void String::replace(const String& find, const String& replace) {
760760
readFrom = wbuffer() + index + find.len();
761761
memmove(readFrom + diff, readFrom, len() - (readFrom - buffer()));
762762
int newLen = len() + diff;
763-
memcpy(wbuffer() + index, replace.buffer(), replace.len());
763+
memmove(wbuffer() + index, replace.buffer(), replace.len());
764764
setLen(newLen);
765765
wbuffer()[newLen] = 0;
766766
index--;

tests/host/core/test_string.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -428,3 +428,15 @@ TEST_CASE("String SSO handles junk in memory", "[core][String]")
428428
REQUIRE(*s == "CO2_defect");
429429
s->~String();
430430
}
431+
432+
433+
TEST_CASE("Issue #5949 - Overlapping src/dest in replace", "[core][String]")
434+
{
435+
String blah = "blah";
436+
blah.replace("xx", "y");
437+
REQUIRE(blah == "blah");
438+
blah.replace("x", "yy");
439+
REQUIRE(blah == "blah");
440+
blah.replace(blah, blah);
441+
REQUIRE(blah == "blah");
442+
}

0 commit comments

Comments
 (0)