ICU-20413 ICU4C: OOM not handled in initStaticTimeZones() in timezone.cpp.
-Use static allocated memory and placement new to avoid OOM failures.
diff --git a/icu4c/source/i18n/timezone.cpp b/icu4c/source/i18n/timezone.cpp
index ccbf467..b8fe13a 100644
--- a/icu4c/source/i18n/timezone.cpp
+++ b/icu4c/source/i18n/timezone.cpp
@@ -115,9 +115,14 @@
 static icu::TimeZone* DEFAULT_ZONE = NULL;
 static icu::UInitOnce gDefaultZoneInitOnce = U_INITONCE_INITIALIZER;
 
-static icu::TimeZone* _GMT = NULL;
-static icu::TimeZone* _UNKNOWN_ZONE = NULL;
+alignas(icu::SimpleTimeZone)
+static char gRawGMT[sizeof(icu::SimpleTimeZone)];
+
+alignas(icu::SimpleTimeZone)
+static char gRawUNKNOWN[sizeof(icu::SimpleTimeZone)];
+
 static icu::UInitOnce gStaticZonesInitOnce = U_INITONCE_INITIALIZER;
+static UBool gStaticZonesInitialized = FALSE; // Whether the static zones are initialized and ready to use.
 
 static char TZDATA_VERSION[16];
 static icu::UInitOnce gTZDataVersionInitOnce = U_INITONCE_INITIALIZER;
@@ -142,11 +147,12 @@
     DEFAULT_ZONE = NULL;
     gDefaultZoneInitOnce.reset();
 
-    delete _GMT;
-    _GMT = NULL;
-    delete _UNKNOWN_ZONE;
-    _UNKNOWN_ZONE = NULL;
-    gStaticZonesInitOnce.reset();
+    if (gStaticZonesInitialized) {
+        reinterpret_cast<SimpleTimeZone*>(gRawGMT)->~SimpleTimeZone();
+        reinterpret_cast<SimpleTimeZone*>(gRawUNKNOWN)->~SimpleTimeZone();
+        gStaticZonesInitialized = FALSE;
+        gStaticZonesInitOnce.reset();
+    }
 
     uprv_memset(TZDATA_VERSION, 0, sizeof(TZDATA_VERSION));
     gTZDataVersionInitOnce.reset();
@@ -304,8 +310,12 @@
     // Initialize _GMT independently of other static data; it should
     // be valid even if we can't load the time zone UDataMemory.
     ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
-    _UNKNOWN_ZONE = new SimpleTimeZone(0, UnicodeString(TRUE, UNKNOWN_ZONE_ID, UNKNOWN_ZONE_ID_LENGTH));
-    _GMT = new SimpleTimeZone(0, UnicodeString(TRUE, GMT_ID, GMT_ID_LENGTH));
+
+    // new can't fail below, as we use placement new into staticly allocated space.
+    new(gRawGMT) SimpleTimeZone(0, UnicodeString(TRUE, GMT_ID, GMT_ID_LENGTH));
+    new(gRawUNKNOWN) SimpleTimeZone(0, UnicodeString(TRUE, UNKNOWN_ZONE_ID, UNKNOWN_ZONE_ID_LENGTH));
+
+    gStaticZonesInitialized = TRUE;
 }
 
 }  // anonymous namespace
@@ -314,14 +324,14 @@
 TimeZone::getUnknown()
 {
     umtx_initOnce(gStaticZonesInitOnce, &initStaticTimeZones);
-    return *_UNKNOWN_ZONE;
+    return *reinterpret_cast<SimpleTimeZone*>(gRawUNKNOWN);
 }
 
 const TimeZone* U_EXPORT2
 TimeZone::getGMT(void)
 {
     umtx_initOnce(gStaticZonesInitOnce, &initStaticTimeZones);
-    return _GMT;
+    return reinterpret_cast<SimpleTimeZone*>(gRawGMT);
 }
 
 // *****************************************************************************
@@ -435,11 +445,8 @@
     if (result == NULL) {
         U_DEBUG_TZ_MSG(("failed to load time zone with id - falling to Etc/Unknown(GMT)"));
         const TimeZone& unknown = getUnknown();
-        if (_UNKNOWN_ZONE == NULL) {                   // Cannot test (&unknown == NULL) because the
-          U_DEBUG_TZ_MSG(("failed to getUnknown()"));  // behavior of NULL references is undefined.
-        } else {
-          result = unknown.clone();
-        }
+        // Unknown zone uses staticly allocated memory, so creation of it can never fail due to OOM.
+        result = unknown.clone();
     }
     return result;
 }
@@ -506,10 +513,7 @@
     // code may also fail.
     if (hostZone == NULL) {
         const TimeZone* temptz = TimeZone::getGMT();
-        // If we can't use GMT, get out.
-        if (temptz == NULL) {
-            return NULL;
-        }
+        // GMT zone uses staticly allocated memory, so creation of it can never fail due to OOM.
         hostZone = temptz->clone();
     }
 
diff --git a/icu4c/source/test/intltest/tztest.cpp b/icu4c/source/test/intltest/tztest.cpp
index 3ab04d2..6b7746f 100644
--- a/icu4c/source/test/intltest/tztest.cpp
+++ b/icu4c/source/test/intltest/tztest.cpp
@@ -72,6 +72,7 @@
     TESTCASE_AUTO(TestGetRegion);
     TESTCASE_AUTO(TestGetAvailableIDsNew);
     TESTCASE_AUTO(TestGetUnknown);
+    TESTCASE_AUTO(TestGetGMT);
     TESTCASE_AUTO(TestGetWindowsID);
     TESTCASE_AUTO(TestGetIDForWindowsID);
     TESTCASE_AUTO_END;
@@ -2420,6 +2421,15 @@
     assertFalse("getUnknown() uses DST", unknown.useDaylightTime());
 }
 
+void TimeZoneTest::TestGetGMT() {
+    const TimeZone *gmt = TimeZone::getGMT();
+    UnicodeString expectedID = UNICODE_STRING_SIMPLE("GMT");
+    UnicodeString id;
+    assertEquals("getGMT() wrong ID", expectedID, gmt->getID(id));
+    assertTrue("getGMT() wrong offset", 0 == gmt->getRawOffset());
+    assertFalse("getGMT() uses DST", gmt->useDaylightTime());
+}
+
 void TimeZoneTest::TestGetWindowsID(void) {
     static const struct {
         const char *id;
diff --git a/icu4c/source/test/intltest/tztest.h b/icu4c/source/test/intltest/tztest.h
index 99a44fe..52feaa2 100644
--- a/icu4c/source/test/intltest/tztest.h
+++ b/icu4c/source/test/intltest/tztest.h
@@ -99,6 +99,7 @@
 
     void TestGetRegion(void);
     void TestGetUnknown();
+    void TestGetGMT();
 
     void TestGetWindowsID(void);
     void TestGetIDForWindowsID(void);