Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ICU-21032 Backport to 64 of ICU-20958 #1155

Merged
merged 1 commit into from
May 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion icu4c/source/common/unistr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1563,7 +1563,11 @@ UnicodeString::doAppend(const UChar *srcChars, int32_t srcStart, int32_t srcLeng
}

int32_t oldLength = length();
int32_t newLength = oldLength + srcLength;
int32_t newLength;
if (uprv_add32_overflow(oldLength, srcLength, &newLength)) {
setToBogus();
return *this;
}

// Check for append onto ourself
const UChar* oldArray = getArrayStart();
Expand Down
62 changes: 62 additions & 0 deletions icu4c/source/test/intltest/ustrtest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ void UnicodeStringTest::runIndexedTest( int32_t index, UBool exec, const char* &
TESTCASE_AUTO(TestWCharPointers);
TESTCASE_AUTO(TestNullPointers);
TESTCASE_AUTO(TestUnicodeStringInsertAppendToSelf);
TESTCASE_AUTO(TestLargeAppend);
TESTCASE_AUTO_END;
}

Expand Down Expand Up @@ -2310,3 +2311,64 @@ void UnicodeStringTest::TestUnicodeStringInsertAppendToSelf() {
str.insert(2, sub);
assertEquals("", u"abbcdcde", str);
}

void UnicodeStringTest::TestLargeAppend() {
if(quick) return;

IcuTestErrorCode status(*this, "TestLargeAppend");
// Make a large UnicodeString
int32_t len = 0xAFFFFFF;
UnicodeString str;
char16_t *buf = str.getBuffer(len);
// A fast way to set buffer to valid Unicode.
// 4E4E is a valid unicode character
uprv_memset(buf, 0x4e, len * 2);
str.releaseBuffer(len);
UnicodeString dest;
// Append it 16 times
// 0xAFFFFFF times 16 is 0xA4FFFFF1,
// which is greater than INT32_MAX, which is 0x7FFFFFFF.
int64_t total = 0;
for (int32_t i = 0; i < 16; i++) {
dest.append(str);
total += len;
if (total <= INT32_MAX) {
assertFalse("dest is not bogus", dest.isBogus());
} else {
assertTrue("dest should be bogus", dest.isBogus());
}
}
dest.remove();
total = 0;
for (int32_t i = 0; i < 16; i++) {
dest.append(str);
total += len;
if (total + len <= INT32_MAX) {
assertFalse("dest is not bogus", dest.isBogus());
} else if (total <= INT32_MAX) {
// Check that a string of exactly the maximum size works
UnicodeString str2;
int32_t remain = INT32_MAX - total;
char16_t *buf2 = str2.getBuffer(remain);
if (buf2 == nullptr) {
// if somehow memory allocation fail, return the test
return;
}
uprv_memset(buf2, 0x4e, remain * 2);
str2.releaseBuffer(remain);
dest.append(str2);
total += remain;
assertEquals("When a string of exactly the maximum size works", (int64_t)INT32_MAX, total);
assertEquals("When a string of exactly the maximum size works", INT32_MAX, dest.length());
assertFalse("dest is not bogus", dest.isBogus());

// Check that a string size+1 goes bogus
str2.truncate(1);
dest.append(str2);
total++;
assertTrue("dest should be bogus", dest.isBogus());
} else {
assertTrue("dest should be bogus", dest.isBogus());
}
}
}
1 change: 1 addition & 0 deletions icu4c/source/test/intltest/ustrtest.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ class UnicodeStringTest: public IntlTest {
void TestWCharPointers();
void TestNullPointers();
void TestUnicodeStringInsertAppendToSelf();
void TestLargeAppend();
};

#endif