Apply 3 upstream CLs beyond 59.1

   http://www.icu-project.org/trac/ticket/12333
   http://www.icu-project.org/trac/ticket/13189
   http://www.icu-project.org/trac/ticket/12635

   - patches/ucase_utf8.patch
   - patches/ucurr_locale.patch
   - patches/collator_range.patch

Bug=chromium:722124
TEST=See the test
TBR=inferno@chromium.org

Change-Id: I3e754734a1c1121c8059a386ca1b5d0f004adb79
Reviewed-on: https://chromium-review.googlesource.com/506592
Reviewed-by: Abhishek Arya <inferno@chromium.org>
Reviewed-by: Jungshik Shin <jshin@chromium.org>
diff --git a/README.chromium b/README.chromium
index 6b1850e..1dce619 100644
--- a/README.chromium
+++ b/README.chromium
@@ -286,4 +286,12 @@
 
    - patches/string_literal_charptr.patch
 
-   
+8. Apply post-59 upstream fixes
+
+   http://www.icu-project.org/trac/ticket/12333
+   http://www.icu-project.org/trac/ticket/13189
+   http://www.icu-project.org/trac/ticket/12635
+
+   - patches/ucase_utf8.patch
+   - patches/ucurr_locale.patch
+   - patches/collator_range.patch
diff --git a/patches/collator_range.patch b/patches/collator_range.patch
new file mode 100644
index 0000000..4d3e383
--- /dev/null
+++ b/patches/collator_range.patch
@@ -0,0 +1,13 @@
+diff --git a/source/i18n/collationweights.cpp b/source/i18n/collationweights.cpp
+index c60da2d8..05458962 100644
+--- a/source/i18n/collationweights.cpp
++++ b/source/i18n/collationweights.cpp
+@@ -527,7 +527,7 @@ CollationWeights::allocWeights(uint32_t lowerLimit, uint32_t upperLimit, int32_t
+ #ifdef UCOL_DEBUG
+         printf("lengthen the short ranges from %ld bytes to %ld and iterate\n", minLength, minLength+1);
+ #endif
+-        for(int32_t i=0; ranges[i].length==minLength; ++i) {
++        for(int32_t i=0; i<rangeCount && ranges[i].length==minLength; ++i) {
+             lengthenRange(ranges[i]);
+         }
+     }
diff --git a/patches/ucase_utf8.patch b/patches/ucase_utf8.patch
new file mode 100644
index 0000000..0780ece
--- /dev/null
+++ b/patches/ucase_utf8.patch
@@ -0,0 +1,58 @@
+diff --git a/source/common/ucase.cpp b/source/common/ucase.cpp
+index 706d7289..6b22f9e3 100644
+--- a/source/common/ucase.cpp
++++ b/source/common/ucase.cpp
+@@ -961,6 +961,7 @@ ucase_toFullLower(UChar32 c,
+                     0307; ; 0307; 0307; tr After_I; # COMBINING DOT ABOVE
+                     0307; ; 0307; 0307; az After_I; # COMBINING DOT ABOVE
+                  */
++                *pString=nullptr;
+                 return 0; /* remove the dot (continue without output) */
+             } else if(loc==UCASE_LOC_TURKISH && c==0x49 && !isFollowedByDotAbove(iter, context)) {
+                 /*
+@@ -1059,6 +1060,7 @@ toUpperOrTitle(UChar32 c,
+ 
+                     0307; 0307; ; ; lt After_Soft_Dotted; # COMBINING DOT ABOVE
+                  */
++                *pString=nullptr;
+                 return 0; /* remove the dot (continue without output) */
+             } else {
+                 /* no known conditional special case mapping, use a normal mapping */
+diff --git a/source/common/ucasemap.cpp b/source/common/ucasemap.cpp
+index 391140d6..1523cb6d 100644
+--- a/source/common/ucasemap.cpp
++++ b/source/common/ucasemap.cpp
+@@ -177,18 +177,22 @@ appendResult(uint8_t *dest, int32_t destIndex, int32_t destCapacity,
+     } else {
+         if(result<=UCASE_MAX_STRING_LENGTH) {
+             // string: "result" is the UTF-16 length
+-            errorCode=U_ZERO_ERROR;
+-            if(destIndex<destCapacity) {
+-                u_strToUTF8((char *)(dest+destIndex), destCapacity-destIndex, &length,
+-                            s, result, &errorCode);
++            if(result==0) {
++                length=0;
+             } else {
+-                u_strToUTF8(NULL, 0, &length, s, result, &errorCode);
+-            }
+-            if(U_FAILURE(errorCode) && errorCode != U_BUFFER_OVERFLOW_ERROR) {
+-                return -1;
+-            }
+-            if(length>(INT32_MAX-destIndex)) {
+-                return -1;  // integer overflow
++                errorCode=U_ZERO_ERROR;
++                if(destIndex<destCapacity) {
++                    u_strToUTF8((char *)(dest+destIndex), destCapacity-destIndex, &length,
++                                s, result, &errorCode);
++                } else {
++                    u_strToUTF8(NULL, 0, &length, s, result, &errorCode);
++                }
++                if(U_FAILURE(errorCode) && errorCode != U_BUFFER_OVERFLOW_ERROR) {
++                    return -1;
++                }
++                if(length>(INT32_MAX-destIndex)) {
++                    return -1;  // integer overflow
++                }
+             }
+             if(edits!=NULL) {
+                 edits->addReplace(cpLength, length);
diff --git a/patches/ucurr_locale.patch b/patches/ucurr_locale.patch
new file mode 100644
index 0000000..062afad
--- /dev/null
+++ b/patches/ucurr_locale.patch
@@ -0,0 +1,212 @@
+diff --git a/source/common/ucurr.cpp b/source/common/ucurr.cpp
+index 885ca3a9..f2cae13c 100644
+--- a/source/common/ucurr.cpp
++++ b/source/common/ucurr.cpp
+@@ -25,6 +25,7 @@
+ #include "uenumimp.h"
+ #include "uhash.h"
+ #include "hash.h"
++#include "uinvchar.h"
+ #include "uresimp.h"
+ #include "ulist.h"
+ #include "ureslocs.h"
+@@ -545,93 +546,97 @@ U_CAPI int32_t U_EXPORT2
+ ucurr_forLocale(const char* locale,
+                 UChar* buff,
+                 int32_t buffCapacity,
+-                UErrorCode* ec)
+-{
+-    int32_t resLen = 0;
+-    const UChar* s = NULL;
+-    if (ec != NULL && U_SUCCESS(*ec)) {
+-        if ((buff && buffCapacity) || !buffCapacity) {
+-            UErrorCode localStatus = U_ZERO_ERROR;
+-            char id[ULOC_FULLNAME_CAPACITY];
+-            if ((resLen = uloc_getKeywordValue(locale, "currency", id, ULOC_FULLNAME_CAPACITY, &localStatus))) {
+-                // there is a currency keyword. Try to see if it's valid
+-                if(buffCapacity > resLen) {
+-                    /* Normalize the currency keyword value to upper case. */
+-                    T_CString_toUpperCase(id);
+-                    u_charsToUChars(id, buff, resLen);
+-                }
+-            } else {
+-                // get country or country_variant in `id'
+-                uint32_t variantType = idForLocale(locale, id, sizeof(id), ec);
++                UErrorCode* ec) {
++    if (U_FAILURE(*ec)) { return 0; }
++    if (buffCapacity < 0 || (buff == nullptr && buffCapacity > 0)) {
++        *ec = U_ILLEGAL_ARGUMENT_ERROR;
++        return 0;
++    }
+ 
+-                if (U_FAILURE(*ec)) {
+-                    return 0;
+-                }
++    char currency[4];  // ISO currency codes are alpha3 codes.
++    UErrorCode localStatus = U_ZERO_ERROR;
++    int32_t resLen = uloc_getKeywordValue(locale, "currency",
++                                          currency, UPRV_LENGTHOF(currency), &localStatus);
++    if (U_SUCCESS(localStatus) && resLen == 3 && uprv_isInvariantString(currency, resLen)) {
++        if (resLen < buffCapacity) {
++            T_CString_toUpperCase(currency);
++            u_charsToUChars(currency, buff, resLen);
++        }
++        return u_terminateUChars(buff, buffCapacity, resLen, ec);
++    }
++
++    // get country or country_variant in `id'
++    char id[ULOC_FULLNAME_CAPACITY];
++    uint32_t variantType = idForLocale(locale, id, UPRV_LENGTHOF(id), ec);
++    if (U_FAILURE(*ec)) {
++        return 0;
++    }
+ 
+ #if !UCONFIG_NO_SERVICE
+-                const UChar* result = CReg::get(id);
+-                if (result) {
+-                    if(buffCapacity > u_strlen(result)) {
+-                        u_strcpy(buff, result);
+-                    }
+-                    return u_strlen(result);
+-                }
++    const UChar* result = CReg::get(id);
++    if (result) {
++        if(buffCapacity > u_strlen(result)) {
++            u_strcpy(buff, result);
++        }
++        resLen = u_strlen(result);
++        return u_terminateUChars(buff, buffCapacity, resLen, ec);
++    }
+ #endif
+-                // Remove variants, which is only needed for registration.
+-                char *idDelim = strchr(id, VAR_DELIM);
+-                if (idDelim) {
+-                    idDelim[0] = 0;
+-                }
++    // Remove variants, which is only needed for registration.
++    char *idDelim = uprv_strchr(id, VAR_DELIM);
++    if (idDelim) {
++        idDelim[0] = 0;
++    }
+ 
+-                // Look up the CurrencyMap element in the root bundle.
+-                UResourceBundle *rb = ures_openDirect(U_ICUDATA_CURR, CURRENCY_DATA, &localStatus);
+-                UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus);
+-                UResourceBundle *countryArray = ures_getByKey(rb, id, cm, &localStatus);
+-                UResourceBundle *currencyReq = ures_getByIndex(countryArray, 0, NULL, &localStatus);
++    const UChar* s;  // Currency code from data file.
++    if (id[0] == 0) {
++        // No point looking in the data for an empty string.
++        // This is what we would get.
++        localStatus = U_MISSING_RESOURCE_ERROR;
++    } else {
++        // Look up the CurrencyMap element in the root bundle.
++        localStatus = U_ZERO_ERROR;
++        UResourceBundle *rb = ures_openDirect(U_ICUDATA_CURR, CURRENCY_DATA, &localStatus);
++        UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus);
++        UResourceBundle *countryArray = ures_getByKey(rb, id, cm, &localStatus);
++        UResourceBundle *currencyReq = ures_getByIndex(countryArray, 0, NULL, &localStatus);
++        s = ures_getStringByKey(currencyReq, "id", &resLen, &localStatus);
++
++        // Get the second item when PREEURO is requested, and this is a known Euro country.
++        // If the requested variant is PREEURO, and this isn't a Euro country,
++        // assume that the country changed over to the Euro in the future.
++        // This is probably an old version of ICU that hasn't been updated yet.
++        // The latest currency is probably correct.
++        if (U_SUCCESS(localStatus)) {
++            if ((variantType & VARIANT_IS_PREEURO) && u_strcmp(s, EUR_STR) == 0) {
++                currencyReq = ures_getByIndex(countryArray, 1, currencyReq, &localStatus);
+                 s = ures_getStringByKey(currencyReq, "id", &resLen, &localStatus);
+-
+-                /*
+-                Get the second item when PREEURO is requested, and this is a known Euro country.
+-                If the requested variant is PREEURO, and this isn't a Euro country, assume
+-                that the country changed over to the Euro in the future. This is probably
+-                an old version of ICU that hasn't been updated yet. The latest currency is
+-                probably correct.
+-                */
+-                if (U_SUCCESS(localStatus)) {
+-                    if ((variantType & VARIANT_IS_PREEURO) && u_strcmp(s, EUR_STR) == 0) {
+-                        currencyReq = ures_getByIndex(countryArray, 1, currencyReq, &localStatus);
+-                        s = ures_getStringByKey(currencyReq, "id", &resLen, &localStatus);
+-                    }
+-                    else if ((variantType & VARIANT_IS_EURO)) {
+-                        s = EUR_STR;
+-                    }
+-                }
+-                ures_close(countryArray);
+-                ures_close(currencyReq);
+-
+-                if ((U_FAILURE(localStatus)) && strchr(id, '_') != 0)
+-                {
+-                    // We don't know about it.  Check to see if we support the variant.
+-                    uloc_getParent(locale, id, sizeof(id), ec);
+-                    *ec = U_USING_FALLBACK_WARNING;
+-                    return ucurr_forLocale(id, buff, buffCapacity, ec);
+-                }
+-                else if (*ec == U_ZERO_ERROR || localStatus != U_ZERO_ERROR) {
+-                    // There is nothing to fallback to. Report the failure/warning if possible.
+-                    *ec = localStatus;
+-                }
+-                if (U_SUCCESS(*ec)) {
+-                    if(buffCapacity > resLen) {
+-                        u_strcpy(buff, s);
+-                    }
+-                }
++            } else if ((variantType & VARIANT_IS_EURO)) {
++                s = EUR_STR;
+             }
+-            return u_terminateUChars(buff, buffCapacity, resLen, ec);
+-        } else {
+-            *ec = U_ILLEGAL_ARGUMENT_ERROR;
+         }
++        ures_close(currencyReq);
++        ures_close(countryArray);
+     }
+-    return resLen;
++
++    if ((U_FAILURE(localStatus)) && strchr(id, '_') != 0) {
++        // We don't know about it.  Check to see if we support the variant.
++        uloc_getParent(locale, id, UPRV_LENGTHOF(id), ec);
++        *ec = U_USING_FALLBACK_WARNING;
++        // TODO: Loop over the shortened id rather than recursing and
++        // looking again for a currency keyword.
++        return ucurr_forLocale(id, buff, buffCapacity, ec);
++    }
++    if (*ec == U_ZERO_ERROR || localStatus != U_ZERO_ERROR) {
++        // There is nothing to fallback to. Report the failure/warning if possible.
++        *ec = localStatus;
++    }
++    if (U_SUCCESS(*ec)) {
++        if(buffCapacity > resLen) {
++            u_strcpy(buff, s);
++        }
++    }
++    return u_terminateUChars(buff, buffCapacity, resLen, ec);
+ }
+ 
+ // end registration
+diff --git a/source/i18n/dcfmtsym.cpp b/source/i18n/dcfmtsym.cpp
+index 08a85b54..43eea49e 100644
+--- a/source/i18n/dcfmtsym.cpp
++++ b/source/i18n/dcfmtsym.cpp
+@@ -433,12 +433,13 @@ DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status, UBool us
+     UErrorCode internalStatus = U_ZERO_ERROR; // don't propagate failures out
+     UChar curriso[4];
+     UnicodeString tempStr;
+-    ucurr_forLocale(locStr, curriso, 4, &internalStatus);
+-
+-    uprv_getStaticCurrencyName(curriso, locStr, tempStr, internalStatus);
+-    if (U_SUCCESS(internalStatus)) {
+-        fSymbols[kIntlCurrencySymbol].setTo(curriso, -1);
+-        fSymbols[kCurrencySymbol] = tempStr;
++    int32_t currisoLength = ucurr_forLocale(locStr, curriso, UPRV_LENGTHOF(curriso), &internalStatus);
++    if (U_SUCCESS(internalStatus) && currisoLength == 3) {
++        uprv_getStaticCurrencyName(curriso, locStr, tempStr, internalStatus);
++        if (U_SUCCESS(internalStatus)) {
++            fSymbols[kIntlCurrencySymbol].setTo(curriso, currisoLength);
++            fSymbols[kCurrencySymbol] = tempStr;
++        }
+     }
+     /* else use the default values. */
+ 
diff --git a/source/common/ucase.cpp b/source/common/ucase.cpp
index 706d728..6b22f9e 100644
--- a/source/common/ucase.cpp
+++ b/source/common/ucase.cpp
@@ -961,6 +961,7 @@
                     0307; ; 0307; 0307; tr After_I; # COMBINING DOT ABOVE
                     0307; ; 0307; 0307; az After_I; # COMBINING DOT ABOVE
                  */
+                *pString=nullptr;
                 return 0; /* remove the dot (continue without output) */
             } else if(loc==UCASE_LOC_TURKISH && c==0x49 && !isFollowedByDotAbove(iter, context)) {
                 /*
@@ -1059,6 +1060,7 @@
 
                     0307; 0307; ; ; lt After_Soft_Dotted; # COMBINING DOT ABOVE
                  */
+                *pString=nullptr;
                 return 0; /* remove the dot (continue without output) */
             } else {
                 /* no known conditional special case mapping, use a normal mapping */
diff --git a/source/common/ucasemap.cpp b/source/common/ucasemap.cpp
index 391140d..1523cb6 100644
--- a/source/common/ucasemap.cpp
+++ b/source/common/ucasemap.cpp
@@ -177,18 +177,22 @@
     } else {
         if(result<=UCASE_MAX_STRING_LENGTH) {
             // string: "result" is the UTF-16 length
-            errorCode=U_ZERO_ERROR;
-            if(destIndex<destCapacity) {
-                u_strToUTF8((char *)(dest+destIndex), destCapacity-destIndex, &length,
-                            s, result, &errorCode);
+            if(result==0) {
+                length=0;
             } else {
-                u_strToUTF8(NULL, 0, &length, s, result, &errorCode);
-            }
-            if(U_FAILURE(errorCode) && errorCode != U_BUFFER_OVERFLOW_ERROR) {
-                return -1;
-            }
-            if(length>(INT32_MAX-destIndex)) {
-                return -1;  // integer overflow
+                errorCode=U_ZERO_ERROR;
+                if(destIndex<destCapacity) {
+                    u_strToUTF8((char *)(dest+destIndex), destCapacity-destIndex, &length,
+                                s, result, &errorCode);
+                } else {
+                    u_strToUTF8(NULL, 0, &length, s, result, &errorCode);
+                }
+                if(U_FAILURE(errorCode) && errorCode != U_BUFFER_OVERFLOW_ERROR) {
+                    return -1;
+                }
+                if(length>(INT32_MAX-destIndex)) {
+                    return -1;  // integer overflow
+                }
             }
             if(edits!=NULL) {
                 edits->addReplace(cpLength, length);
diff --git a/source/common/ucurr.cpp b/source/common/ucurr.cpp
index 885ca3a..f2cae13 100644
--- a/source/common/ucurr.cpp
+++ b/source/common/ucurr.cpp
@@ -25,6 +25,7 @@
 #include "uenumimp.h"
 #include "uhash.h"
 #include "hash.h"
+#include "uinvchar.h"
 #include "uresimp.h"
 #include "ulist.h"
 #include "ureslocs.h"
@@ -545,93 +546,97 @@
 ucurr_forLocale(const char* locale,
                 UChar* buff,
                 int32_t buffCapacity,
-                UErrorCode* ec)
-{
-    int32_t resLen = 0;
-    const UChar* s = NULL;
-    if (ec != NULL && U_SUCCESS(*ec)) {
-        if ((buff && buffCapacity) || !buffCapacity) {
-            UErrorCode localStatus = U_ZERO_ERROR;
-            char id[ULOC_FULLNAME_CAPACITY];
-            if ((resLen = uloc_getKeywordValue(locale, "currency", id, ULOC_FULLNAME_CAPACITY, &localStatus))) {
-                // there is a currency keyword. Try to see if it's valid
-                if(buffCapacity > resLen) {
-                    /* Normalize the currency keyword value to upper case. */
-                    T_CString_toUpperCase(id);
-                    u_charsToUChars(id, buff, resLen);
-                }
-            } else {
-                // get country or country_variant in `id'
-                uint32_t variantType = idForLocale(locale, id, sizeof(id), ec);
+                UErrorCode* ec) {
+    if (U_FAILURE(*ec)) { return 0; }
+    if (buffCapacity < 0 || (buff == nullptr && buffCapacity > 0)) {
+        *ec = U_ILLEGAL_ARGUMENT_ERROR;
+        return 0;
+    }
 
-                if (U_FAILURE(*ec)) {
-                    return 0;
-                }
+    char currency[4];  // ISO currency codes are alpha3 codes.
+    UErrorCode localStatus = U_ZERO_ERROR;
+    int32_t resLen = uloc_getKeywordValue(locale, "currency",
+                                          currency, UPRV_LENGTHOF(currency), &localStatus);
+    if (U_SUCCESS(localStatus) && resLen == 3 && uprv_isInvariantString(currency, resLen)) {
+        if (resLen < buffCapacity) {
+            T_CString_toUpperCase(currency);
+            u_charsToUChars(currency, buff, resLen);
+        }
+        return u_terminateUChars(buff, buffCapacity, resLen, ec);
+    }
+
+    // get country or country_variant in `id'
+    char id[ULOC_FULLNAME_CAPACITY];
+    uint32_t variantType = idForLocale(locale, id, UPRV_LENGTHOF(id), ec);
+    if (U_FAILURE(*ec)) {
+        return 0;
+    }
 
 #if !UCONFIG_NO_SERVICE
-                const UChar* result = CReg::get(id);
-                if (result) {
-                    if(buffCapacity > u_strlen(result)) {
-                        u_strcpy(buff, result);
-                    }
-                    return u_strlen(result);
-                }
+    const UChar* result = CReg::get(id);
+    if (result) {
+        if(buffCapacity > u_strlen(result)) {
+            u_strcpy(buff, result);
+        }
+        resLen = u_strlen(result);
+        return u_terminateUChars(buff, buffCapacity, resLen, ec);
+    }
 #endif
-                // Remove variants, which is only needed for registration.
-                char *idDelim = strchr(id, VAR_DELIM);
-                if (idDelim) {
-                    idDelim[0] = 0;
-                }
+    // Remove variants, which is only needed for registration.
+    char *idDelim = uprv_strchr(id, VAR_DELIM);
+    if (idDelim) {
+        idDelim[0] = 0;
+    }
 
-                // Look up the CurrencyMap element in the root bundle.
-                UResourceBundle *rb = ures_openDirect(U_ICUDATA_CURR, CURRENCY_DATA, &localStatus);
-                UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus);
-                UResourceBundle *countryArray = ures_getByKey(rb, id, cm, &localStatus);
-                UResourceBundle *currencyReq = ures_getByIndex(countryArray, 0, NULL, &localStatus);
+    const UChar* s;  // Currency code from data file.
+    if (id[0] == 0) {
+        // No point looking in the data for an empty string.
+        // This is what we would get.
+        localStatus = U_MISSING_RESOURCE_ERROR;
+    } else {
+        // Look up the CurrencyMap element in the root bundle.
+        localStatus = U_ZERO_ERROR;
+        UResourceBundle *rb = ures_openDirect(U_ICUDATA_CURR, CURRENCY_DATA, &localStatus);
+        UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus);
+        UResourceBundle *countryArray = ures_getByKey(rb, id, cm, &localStatus);
+        UResourceBundle *currencyReq = ures_getByIndex(countryArray, 0, NULL, &localStatus);
+        s = ures_getStringByKey(currencyReq, "id", &resLen, &localStatus);
+
+        // Get the second item when PREEURO is requested, and this is a known Euro country.
+        // If the requested variant is PREEURO, and this isn't a Euro country,
+        // assume that the country changed over to the Euro in the future.
+        // This is probably an old version of ICU that hasn't been updated yet.
+        // The latest currency is probably correct.
+        if (U_SUCCESS(localStatus)) {
+            if ((variantType & VARIANT_IS_PREEURO) && u_strcmp(s, EUR_STR) == 0) {
+                currencyReq = ures_getByIndex(countryArray, 1, currencyReq, &localStatus);
                 s = ures_getStringByKey(currencyReq, "id", &resLen, &localStatus);
-
-                /*
-                Get the second item when PREEURO is requested, and this is a known Euro country.
-                If the requested variant is PREEURO, and this isn't a Euro country, assume
-                that the country changed over to the Euro in the future. This is probably
-                an old version of ICU that hasn't been updated yet. The latest currency is
-                probably correct.
-                */
-                if (U_SUCCESS(localStatus)) {
-                    if ((variantType & VARIANT_IS_PREEURO) && u_strcmp(s, EUR_STR) == 0) {
-                        currencyReq = ures_getByIndex(countryArray, 1, currencyReq, &localStatus);
-                        s = ures_getStringByKey(currencyReq, "id", &resLen, &localStatus);
-                    }
-                    else if ((variantType & VARIANT_IS_EURO)) {
-                        s = EUR_STR;
-                    }
-                }
-                ures_close(countryArray);
-                ures_close(currencyReq);
-
-                if ((U_FAILURE(localStatus)) && strchr(id, '_') != 0)
-                {
-                    // We don't know about it.  Check to see if we support the variant.
-                    uloc_getParent(locale, id, sizeof(id), ec);
-                    *ec = U_USING_FALLBACK_WARNING;
-                    return ucurr_forLocale(id, buff, buffCapacity, ec);
-                }
-                else if (*ec == U_ZERO_ERROR || localStatus != U_ZERO_ERROR) {
-                    // There is nothing to fallback to. Report the failure/warning if possible.
-                    *ec = localStatus;
-                }
-                if (U_SUCCESS(*ec)) {
-                    if(buffCapacity > resLen) {
-                        u_strcpy(buff, s);
-                    }
-                }
+            } else if ((variantType & VARIANT_IS_EURO)) {
+                s = EUR_STR;
             }
-            return u_terminateUChars(buff, buffCapacity, resLen, ec);
-        } else {
-            *ec = U_ILLEGAL_ARGUMENT_ERROR;
+        }
+        ures_close(currencyReq);
+        ures_close(countryArray);
+    }
+
+    if ((U_FAILURE(localStatus)) && strchr(id, '_') != 0) {
+        // We don't know about it.  Check to see if we support the variant.
+        uloc_getParent(locale, id, UPRV_LENGTHOF(id), ec);
+        *ec = U_USING_FALLBACK_WARNING;
+        // TODO: Loop over the shortened id rather than recursing and
+        // looking again for a currency keyword.
+        return ucurr_forLocale(id, buff, buffCapacity, ec);
+    }
+    if (*ec == U_ZERO_ERROR || localStatus != U_ZERO_ERROR) {
+        // There is nothing to fallback to. Report the failure/warning if possible.
+        *ec = localStatus;
+    }
+    if (U_SUCCESS(*ec)) {
+        if(buffCapacity > resLen) {
+            u_strcpy(buff, s);
         }
     }
-    return resLen;
+    return u_terminateUChars(buff, buffCapacity, resLen, ec);
 }
 
 // end registration
diff --git a/source/i18n/collationweights.cpp b/source/i18n/collationweights.cpp
index c60da2d..0545896 100644
--- a/source/i18n/collationweights.cpp
+++ b/source/i18n/collationweights.cpp
@@ -527,7 +527,7 @@
 #ifdef UCOL_DEBUG
         printf("lengthen the short ranges from %ld bytes to %ld and iterate\n", minLength, minLength+1);
 #endif
-        for(int32_t i=0; ranges[i].length==minLength; ++i) {
+        for(int32_t i=0; i<rangeCount && ranges[i].length==minLength; ++i) {
             lengthenRange(ranges[i]);
         }
     }
diff --git a/source/i18n/dcfmtsym.cpp b/source/i18n/dcfmtsym.cpp
index 08a85b5..43eea49 100644
--- a/source/i18n/dcfmtsym.cpp
+++ b/source/i18n/dcfmtsym.cpp
@@ -433,12 +433,13 @@
     UErrorCode internalStatus = U_ZERO_ERROR; // don't propagate failures out
     UChar curriso[4];
     UnicodeString tempStr;
-    ucurr_forLocale(locStr, curriso, 4, &internalStatus);
-
-    uprv_getStaticCurrencyName(curriso, locStr, tempStr, internalStatus);
-    if (U_SUCCESS(internalStatus)) {
-        fSymbols[kIntlCurrencySymbol].setTo(curriso, -1);
-        fSymbols[kCurrencySymbol] = tempStr;
+    int32_t currisoLength = ucurr_forLocale(locStr, curriso, UPRV_LENGTHOF(curriso), &internalStatus);
+    if (U_SUCCESS(internalStatus) && currisoLength == 3) {
+        uprv_getStaticCurrencyName(curriso, locStr, tempStr, internalStatus);
+        if (U_SUCCESS(internalStatus)) {
+            fSymbols[kIntlCurrencySymbol].setTo(curriso, currisoLength);
+            fSymbols[kCurrencySymbol] = tempStr;
+        }
     }
     /* else use the default values. */