diff --git a/README.chromium b/README.chromium
index f2ff451..1301d73 100644
--- a/README.chromium
+++ b/README.chromium
@@ -288,3 +288,10 @@
   - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=68895
   - https://issues.chromium.org/u/1/issues/345352978
   - https://unicode-org.atlassian.net/browse/ICU-22730
+
+17. Patch UnicodeString to fix heap-buffer-overflow .
+    patches/unicode_string.patch
+  - https://unicode-org.atlassian.net/browse/ICU-23060
+  - https://g-issues.chromium.org/issues/393989622
+  - https://patch-diff.githubusercontent.com/raw/unicode-org/icu/pull/3416.diff
+  - https://patch-diff.githubusercontent.com/raw/unicode-org/icu/pull/3420.diff
diff --git a/patches/unicode_string.patch b/patches/unicode_string.patch
new file mode 100644
index 0000000..12d9cdb
--- /dev/null
+++ b/patches/unicode_string.patch
@@ -0,0 +1,105 @@
+diff --git a/source/common/unistr.cpp b/source/common/unistr.cpp
+index 04f01cfa..626f8886 100644
+--- a/source/common/unistr.cpp
++++ b/source/common/unistr.cpp
+@@ -1865,6 +1865,13 @@ UnicodeString::cloneArrayIfNeeded(int32_t newCapacity,
+       growCapacity = newCapacity;
+     } else if(newCapacity <= US_STACKBUF_SIZE && growCapacity > US_STACKBUF_SIZE) {
+       growCapacity = US_STACKBUF_SIZE;
++    } else if(newCapacity > growCapacity) {
++      setToBogus();
++      return false;  // bad inputs
++    }
++    if(growCapacity > kMaxCapacity) {
++      setToBogus();
++      return false;
+     }
+ 
+     // save old values
+diff --git a/source/test/intltest/ustrtest.cpp b/source/test/intltest/ustrtest.cpp
+index 26c51b9c..71ebde4b 100644
+--- a/source/test/intltest/ustrtest.cpp
++++ b/source/test/intltest/ustrtest.cpp
+@@ -68,6 +68,7 @@ void UnicodeStringTest::runIndexedTest( int32_t index, UBool exec, const char* &
+     TESTCASE_AUTO(TestNullPointers);
+     TESTCASE_AUTO(TestUnicodeStringInsertAppendToSelf);
+     TESTCASE_AUTO(TestLargeAppend);
++    TESTCASE_AUTO(TestLargeMemory);
+     TESTCASE_AUTO_END;
+ }
+ 
+@@ -2328,6 +2329,18 @@ void UnicodeStringTest::TestUnicodeStringInsertAppendToSelf() {
+     assertEquals("", u"abbcdcde", str);
+ }
+ 
++void UnicodeStringTest::TestLargeMemory() {
++#if U_PLATFORM_IS_LINUX_BASED || U_PLATFORM_IS_DARWIN_BASED
++    if(quick) { return; }
++    IcuTestErrorCode status(*this, "TestLargeMemory");
++    constexpr uint32_t len = 2147483643;
++    char16_t *buf = new char16_t[len];
++    if (buf == nullptr) { return; }
++    uprv_memset(buf, 0x4e, len * 2);
++    icu::UnicodeString test(buf, len);
++    delete [] buf;
++#endif
++}
+ void UnicodeStringTest::TestLargeAppend() {
+     if(quick) return;
+ 
+@@ -2356,15 +2369,17 @@ void UnicodeStringTest::TestLargeAppend() {
+     }
+     dest.remove();
+     total = 0;
++    // Copy kMaxCapacity from common/unistr.cpp
++    const int32_t kMaxCapacity = 0x7ffffff5;
+     for (int32_t i = 0; i < 16; i++) {
+         dest.append(str);
+         total += len;
+-        if (total + len <= INT32_MAX) {
++        if (total + len <= kMaxCapacity) {
+             assertFalse("dest is not bogus", dest.isBogus());
+-        } else if (total <= INT32_MAX) {
++        } else if (total <= kMaxCapacity) {
+             // Check that a string of exactly the maximum size works
+             UnicodeString str2;
+-            int32_t remain = static_cast<int32_t>(INT32_MAX - total);
++            int32_t remain = static_cast<int32_t>(kMaxCapacity - total);
+             char16_t *buf2 = str2.getBuffer(remain);
+             if (buf2 == nullptr) {
+                 // if somehow memory allocation fail, return the test
+@@ -2374,14 +2389,19 @@ void UnicodeStringTest::TestLargeAppend() {
+             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());
++            assertEquals("When a string of exactly the maximum size works", static_cast<int64_t>(kMaxCapacity), total);
++            assertEquals("When a string of exactly the maximum size works", kMaxCapacity, dest.length());
+             assertFalse("dest is not bogus", dest.isBogus());
+ 
+-            // Check that a string size+1 goes bogus
++            // Check that a string size+1 does not go bogus (one more byte reserved for NUL)
+             str2.truncate(1);
+             dest.append(str2);
+             total++;
++            assertFalse("dest should be not bogus", dest.isBogus());
++            // Check that a string size+2 goes bogus (beyond the byte reserved
++            // for NUL)
++            dest.append(str2);
++            total++;
+             assertTrue("dest should be bogus", dest.isBogus());
+         } else {
+             assertTrue("dest should be bogus", dest.isBogus());
+diff --git a/source/test/intltest/ustrtest.h b/source/test/intltest/ustrtest.h
+index 088b7139..9e50d365 100644
+--- a/source/test/intltest/ustrtest.h
++++ b/source/test/intltest/ustrtest.h
+@@ -92,6 +92,7 @@ public:
+     void TestUnicodeStringImplementsAppendable();
+     void TestSizeofUnicodeString();
+     void TestMoveSwap();
++    void TestLargeMemory();
+ 
+     void TestUInt16Pointers();
+     void TestWCharPointers();
diff --git a/source/common/unistr.cpp b/source/common/unistr.cpp
index 04f01cf..626f888 100644
--- a/source/common/unistr.cpp
+++ b/source/common/unistr.cpp
@@ -1865,6 +1865,13 @@
       growCapacity = newCapacity;
     } else if(newCapacity <= US_STACKBUF_SIZE && growCapacity > US_STACKBUF_SIZE) {
       growCapacity = US_STACKBUF_SIZE;
+    } else if(newCapacity > growCapacity) {
+      setToBogus();
+      return false;  // bad inputs
+    }
+    if(growCapacity > kMaxCapacity) {
+      setToBogus();
+      return false;
     }
 
     // save old values
diff --git a/source/test/intltest/ustrtest.cpp b/source/test/intltest/ustrtest.cpp
index 26c51b9..71ebde4 100644
--- a/source/test/intltest/ustrtest.cpp
+++ b/source/test/intltest/ustrtest.cpp
@@ -68,6 +68,7 @@
     TESTCASE_AUTO(TestNullPointers);
     TESTCASE_AUTO(TestUnicodeStringInsertAppendToSelf);
     TESTCASE_AUTO(TestLargeAppend);
+    TESTCASE_AUTO(TestLargeMemory);
     TESTCASE_AUTO_END;
 }
 
@@ -2328,6 +2329,18 @@
     assertEquals("", u"abbcdcde", str);
 }
 
+void UnicodeStringTest::TestLargeMemory() {
+#if U_PLATFORM_IS_LINUX_BASED || U_PLATFORM_IS_DARWIN_BASED
+    if(quick) { return; }
+    IcuTestErrorCode status(*this, "TestLargeMemory");
+    constexpr uint32_t len = 2147483643;
+    char16_t *buf = new char16_t[len];
+    if (buf == nullptr) { return; }
+    uprv_memset(buf, 0x4e, len * 2);
+    icu::UnicodeString test(buf, len);
+    delete [] buf;
+#endif
+}
 void UnicodeStringTest::TestLargeAppend() {
     if(quick) return;
 
@@ -2356,15 +2369,17 @@
     }
     dest.remove();
     total = 0;
+    // Copy kMaxCapacity from common/unistr.cpp
+    const int32_t kMaxCapacity = 0x7ffffff5;
     for (int32_t i = 0; i < 16; i++) {
         dest.append(str);
         total += len;
-        if (total + len <= INT32_MAX) {
+        if (total + len <= kMaxCapacity) {
             assertFalse("dest is not bogus", dest.isBogus());
-        } else if (total <= INT32_MAX) {
+        } else if (total <= kMaxCapacity) {
             // Check that a string of exactly the maximum size works
             UnicodeString str2;
-            int32_t remain = static_cast<int32_t>(INT32_MAX - total);
+            int32_t remain = static_cast<int32_t>(kMaxCapacity - total);
             char16_t *buf2 = str2.getBuffer(remain);
             if (buf2 == nullptr) {
                 // if somehow memory allocation fail, return the test
@@ -2374,14 +2389,19 @@
             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());
+            assertEquals("When a string of exactly the maximum size works", static_cast<int64_t>(kMaxCapacity), total);
+            assertEquals("When a string of exactly the maximum size works", kMaxCapacity, dest.length());
             assertFalse("dest is not bogus", dest.isBogus());
 
-            // Check that a string size+1 goes bogus
+            // Check that a string size+1 does not go bogus (one more byte reserved for NUL)
             str2.truncate(1);
             dest.append(str2);
             total++;
+            assertFalse("dest should be not bogus", dest.isBogus());
+            // Check that a string size+2 goes bogus (beyond the byte reserved
+            // for NUL)
+            dest.append(str2);
+            total++;
             assertTrue("dest should be bogus", dest.isBogus());
         } else {
             assertTrue("dest should be bogus", dest.isBogus());
diff --git a/source/test/intltest/ustrtest.h b/source/test/intltest/ustrtest.h
index 088b713..9e50d36 100644
--- a/source/test/intltest/ustrtest.h
+++ b/source/test/intltest/ustrtest.h
@@ -92,6 +92,7 @@
     void TestUnicodeStringImplementsAppendable();
     void TestSizeofUnicodeString();
     void TestMoveSwap();
+    void TestLargeMemory();
 
     void TestUInt16Pointers();
     void TestWCharPointers();