1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-22 21:23:07 +03:00

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
This commit is contained in:
Earle F. Philhower, III 2019-04-10 17:21:15 +03:00 committed by GitHub
parent 4b596d8fb1
commit 9712170276
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 18 additions and 6 deletions

View File

@ -237,7 +237,7 @@ void String::move(String &rhs) {
} }
if (rhs.sso()) { if (rhs.sso()) {
setSSO(true); setSSO(true);
memcpy(sso_buf, rhs.sso_buf, sizeof(sso_buf)); memmove(sso_buf, rhs.sso_buf, sizeof(sso_buf));
} else { } else {
setSSO(false); setSSO(false);
setBuffer(rhs.wbuffer()); setBuffer(rhs.wbuffer());
@ -730,21 +730,21 @@ void String::replace(const String& find, const String& replace) {
char *foundAt; char *foundAt;
if(diff == 0) { if(diff == 0) {
while((foundAt = strstr(readFrom, find.buffer())) != NULL) { while((foundAt = strstr(readFrom, find.buffer())) != NULL) {
memcpy(foundAt, replace.buffer(), replace.len()); memmove(foundAt, replace.buffer(), replace.len());
readFrom = foundAt + replace.len(); readFrom = foundAt + replace.len();
} }
} else if(diff < 0) { } else if(diff < 0) {
char *writeTo = wbuffer(); char *writeTo = wbuffer();
while((foundAt = strstr(readFrom, find.buffer())) != NULL) { while((foundAt = strstr(readFrom, find.buffer())) != NULL) {
unsigned int n = foundAt - readFrom; unsigned int n = foundAt - readFrom;
memcpy(writeTo, readFrom, n); memmove(writeTo, readFrom, n);
writeTo += n; writeTo += n;
memcpy(writeTo, replace.buffer(), replace.len()); memmove(writeTo, replace.buffer(), replace.len());
writeTo += replace.len(); writeTo += replace.len();
readFrom = foundAt + find.len(); readFrom = foundAt + find.len();
setLen(len() + diff); setLen(len() + diff);
} }
strcpy(writeTo, readFrom); memmove(writeTo, readFrom, strlen(readFrom)+1);
} else { } else {
unsigned int size = len(); // compute size needed for result unsigned int size = len(); // compute size needed for result
while((foundAt = strstr(readFrom, find.buffer())) != NULL) { while((foundAt = strstr(readFrom, find.buffer())) != NULL) {
@ -760,7 +760,7 @@ void String::replace(const String& find, const String& replace) {
readFrom = wbuffer() + index + find.len(); readFrom = wbuffer() + index + find.len();
memmove(readFrom + diff, readFrom, len() - (readFrom - buffer())); memmove(readFrom + diff, readFrom, len() - (readFrom - buffer()));
int newLen = len() + diff; int newLen = len() + diff;
memcpy(wbuffer() + index, replace.buffer(), replace.len()); memmove(wbuffer() + index, replace.buffer(), replace.len());
setLen(newLen); setLen(newLen);
wbuffer()[newLen] = 0; wbuffer()[newLen] = 0;
index--; index--;

View File

@ -428,3 +428,15 @@ TEST_CASE("String SSO handles junk in memory", "[core][String]")
REQUIRE(*s == "CO2_defect"); REQUIRE(*s == "CO2_defect");
s->~String(); s->~String();
} }
TEST_CASE("Issue #5949 - Overlapping src/dest in replace", "[core][String]")
{
String blah = "blah";
blah.replace("xx", "y");
REQUIRE(blah == "blah");
blah.replace("x", "yy");
REQUIRE(blah == "blah");
blah.replace(blah, blah);
REQUIRE(blah == "blah");
}