| From b7d08bc04a4296982fcef8b6b8a354a9e4e7afca Mon Sep 17 00:00:00 2001 |
| From: Frank Tang <ftang@chromium.org> |
| Date: Sat, 1 Feb 2020 02:39:04 +0000 |
| Subject: [PATCH] ICU-20958 Prevent SEGV_MAPERR in append |
| |
| See #971 |
| |
| Upstream-Status: Accepted |
| CVE: CVE-2020-10531 |
| |
| Reference to upstream patch: |
| https://github.com/unicode-org/icu/commit/b7d08bc04a4296982fcef8b6b8a354a9e4e7afca |
| |
| --- |
| common/unistr.cpp | 6 ++- |
| test/intltest/ustrtest.cpp | 62 +++++++++++++++++++++++++++++++ |
| test/intltest/ustrtest.h | 1 + |
| 3 files changed, 68 insertions(+), 1 deletion(-) |
| |
| diff --git a/common/unistr.cpp b/common/unistr.cpp |
| index 901bb33..6ea0915 100644 |
| --- a/common/unistr.cpp |
| +++ b/common/unistr.cpp |
| @@ -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(); |
| diff --git a/test/intltest/ustrtest.cpp b/test/intltest/ustrtest.cpp |
| index b6515ea..ad38bdf 100644 |
| --- a/test/intltest/ustrtest.cpp |
| +++ b/test/intltest/ustrtest.cpp |
| @@ -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; |
| } |
| |
| @@ -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()); |
| + } |
| + } |
| +} |
| diff --git a/test/intltest/ustrtest.h b/test/intltest/ustrtest.h |
| index 218befd..4a356a9 100644 |
| --- a/test/intltest/ustrtest.h |
| +++ b/test/intltest/ustrtest.h |
| @@ -97,6 +97,7 @@ public: |
| void TestWCharPointers(); |
| void TestNullPointers(); |
| void TestUnicodeStringInsertAppendToSelf(); |
| + void TestLargeAppend(); |
| }; |
| |
| #endif |
| -- |
| 2.17.1 |
| |