Fix icu::OlsonTimeZone::getHistoricalOffset crash

The icu::TimeZone::adoptDefault may delete a old default timezone
while anther thread is calling the clone() to that old default timezone
in the createDefault running on another thread. Need to protect the
delete and DEFAULT_ZONE->clone() running concurrently. Otherwise, the
returned cloned TimeZone could contains partially trashed data and
cause crash later on.

test in https://chromium-review.googlesource.com/c/v8/v8/+/1601370

Upstream bug: https://unicode-org.atlassian.net/browse/ICU-20595
upstream PR: https://github.com/unicode-org/icu/pull/649/

Bug: chromium:950851
Test: v8 unittests - DateCache:AdoptDefault*
Change-Id: Ic8a1c374f20a50f5ebd567df8d34a65987315a7e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/deps/icu/+/1602037
Reviewed-by: Jungshik Shin <jshin@chromium.org>
diff --git a/README.chromium b/README.chromium
index 1d82edc..c75f49a 100644
--- a/README.chromium
+++ b/README.chromium
@@ -258,3 +258,10 @@
     https://unicode-org.atlassian.net/browse/ICU-20391
   - upstream PR:
     https://github.com/unicode-org/icu/pull/628
+
+9. Timezone breakage patch
+  - patches/timezone.patch
+  - upstream bug:
+    https://unicode-org.atlassian.net/browse/ICU-20595
+  - upstream PR:
+    https://github.com/unicode-org/icu/pull/649
diff --git a/patches/timezone.patch b/patches/timezone.patch
new file mode 100644
index 0000000..d456d6f
--- /dev/null
+++ b/patches/timezone.patch
@@ -0,0 +1,51 @@
+diff --git a/source/i18n/timezone.cpp b/source/i18n/timezone.cpp
+index f129d8b6..f7b48273 100644
+--- a/source/i18n/timezone.cpp
++++ b/source/i18n/timezone.cpp
+@@ -527,6 +527,11 @@ TimeZone::detectHostTimeZone()
+ 
+ // -------------------------------------
+ 
++static UMutex *gMutex() {
++    static UMutex* m = new UMutex();
++    return m;
++}
++
+ /**
+  * Initialize DEFAULT_ZONE from the system default time zone.  
+  * Upon return, DEFAULT_ZONE will not be NULL, unless operator new()
+@@ -536,6 +541,7 @@ static void U_CALLCONV initDefault()
+ {
+     ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
+ 
++    Mutex lock(gMutex());
+     // If setDefault() has already been called we can skip getting the
+     // default zone information from the system.
+     if (DEFAULT_ZONE != NULL) {
+@@ -571,7 +577,11 @@ TimeZone* U_EXPORT2
+ TimeZone::createDefault()
+ {
+     umtx_initOnce(gDefaultZoneInitOnce, initDefault);
+-    return (DEFAULT_ZONE != NULL) ? DEFAULT_ZONE->clone() : NULL;
++    if (DEFAULT_ZONE == NULL) return NULL;
++    {
++        Mutex lock(gMutex());
++        return DEFAULT_ZONE->clone();
++    }
+ }
+ 
+ // -------------------------------------
+@@ -582,8 +592,11 @@ TimeZone::adoptDefault(TimeZone* zone)
+     if (zone != NULL)
+     {
+         TimeZone *old = DEFAULT_ZONE;
+-        DEFAULT_ZONE = zone;
+-        delete old;
++        {
++            Mutex lock(gMutex());
++            DEFAULT_ZONE = zone;
++            delete old;
++        }
+         ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
+     }
+ }
diff --git a/source/i18n/timezone.cpp b/source/i18n/timezone.cpp
index f129d8b..f7b4827 100644
--- a/source/i18n/timezone.cpp
+++ b/source/i18n/timezone.cpp
@@ -527,6 +527,11 @@
 
 // -------------------------------------
 
+static UMutex *gMutex() {
+    static UMutex* m = new UMutex();
+    return m;
+}
+
 /**
  * Initialize DEFAULT_ZONE from the system default time zone.  
  * Upon return, DEFAULT_ZONE will not be NULL, unless operator new()
@@ -536,6 +541,7 @@
 {
     ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
 
+    Mutex lock(gMutex());
     // If setDefault() has already been called we can skip getting the
     // default zone information from the system.
     if (DEFAULT_ZONE != NULL) {
@@ -571,7 +577,11 @@
 TimeZone::createDefault()
 {
     umtx_initOnce(gDefaultZoneInitOnce, initDefault);
-    return (DEFAULT_ZONE != NULL) ? DEFAULT_ZONE->clone() : NULL;
+    if (DEFAULT_ZONE == NULL) return NULL;
+    {
+        Mutex lock(gMutex());
+        return DEFAULT_ZONE->clone();
+    }
 }
 
 // -------------------------------------
@@ -582,8 +592,11 @@
     if (zone != NULL)
     {
         TimeZone *old = DEFAULT_ZONE;
-        DEFAULT_ZONE = zone;
-        delete old;
+        {
+            Mutex lock(gMutex());
+            DEFAULT_ZONE = zone;
+            delete old;
+        }
         ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
     }
 }