summaryrefslogtreecommitdiffstats
path: root/meta/recipes-support/icu/icu/CVE-2020-10531.patch
blob: 6697b27dc8fa6536bb575292267d4f80466e9cf1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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