diff --git a/icu4c/source/common/cmemory.h b/icu4c/source/common/cmemory.h index 313180b29fb..754bbb5713f 100644 --- a/icu4c/source/common/cmemory.h +++ b/icu4c/source/common/cmemory.h @@ -297,12 +297,16 @@ public: * Automatically allocates the heap array if the argument is larger than the stack capacity. * Intended for use when an approximate capacity is known at compile time but the true * capacity is not known until runtime. - * - * WARNING: does not report errors upon memory allocation failure, after - * which capacity will be stackCapacity, not the requested newCapacity. */ - MaybeStackArray(int32_t newCapacity) : MaybeStackArray() { - if (capacity < newCapacity) { resize(newCapacity); } + MaybeStackArray(int32_t newCapacity, UErrorCode status) : MaybeStackArray() { + if (U_FAILURE(status)) { + return; + } + if (capacity < newCapacity) { + if (resize(newCapacity) == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + } + } } /** * Destructor deletes the array (if owned). diff --git a/icu4c/source/common/localematcher.cpp b/icu4c/source/common/localematcher.cpp index bb18e236c4e..8efbf0b28b6 100644 --- a/icu4c/source/common/localematcher.cpp +++ b/icu4c/source/common/localematcher.cpp @@ -436,11 +436,8 @@ LocaleMatcher::LocaleMatcher(const Builder &builder, UErrorCode &errorCode) : int32_t suppLength = 0; // Determine insertion order. // Add locales immediately that are equivalent to the default. - MaybeStackArray order(supportedLocalesLength); - if (order.getAlias() == nullptr) { - errorCode = U_MEMORY_ALLOCATION_ERROR; - return; - } + MaybeStackArray order(supportedLocalesLength, errorCode); + if (U_FAILURE(errorCode)) { return; } int32_t numParadigms = 0; for (int32_t i = 0; i < supportedLocalesLength; ++i) { const Locale &locale = *supportedLocales[i]; diff --git a/icu4c/source/i18n/listformatter.cpp b/icu4c/source/i18n/listformatter.cpp index da99c9291d1..84f24d2c659 100644 --- a/icu4c/source/i18n/listformatter.cpp +++ b/icu4c/source/i18n/listformatter.cpp @@ -702,7 +702,7 @@ UnicodeString& ListFormatter::format_( int32_t prefixLength = 0; // for n items, there are 2 * (n + 1) boundary including 0 and the upper // edge. - MaybeStackArray offsets((handler != nullptr) ? 2 * (nItems + 1): 0); + MaybeStackArray offsets((handler != nullptr) ? 2 * (nItems + 1) : 0, errorCode); if (nItems == 2) { joinStringsAndReplace( data->patternHandler->getTwoPattern(items[1]), diff --git a/icu4c/source/i18n/number_decimalquantity.cpp b/icu4c/source/i18n/number_decimalquantity.cpp index 482e93dc7a1..e646c546458 100644 --- a/icu4c/source/i18n/number_decimalquantity.cpp +++ b/icu4c/source/i18n/number_decimalquantity.cpp @@ -20,6 +20,7 @@ #include "charstr.h" #include "number_utils.h" #include "uassert.h" +#include "util.h" using namespace icu; using namespace icu::number; @@ -634,7 +635,10 @@ void DecimalQuantity::toDecNum(DecNum& output, UErrorCode& status) const { // Use the BCD constructor. We need to do a little bit of work to convert, though. // The decNumber constructor expects most-significant first, but we store least-significant first. - MaybeStackArray ubcd(precision); + MaybeStackArray ubcd(precision, status); + if (U_FAILURE(status)) { + return; + } for (int32_t m = 0; m < precision; m++) { ubcd[precision - m - 1] = static_cast(getDigitPos(m)); } @@ -1324,7 +1328,11 @@ bool DecimalQuantity::operator==(const DecimalQuantity& other) const { } UnicodeString DecimalQuantity::toString() const { - MaybeStackArray digits(precision + 1); + UErrorCode localStatus = U_ZERO_ERROR; + MaybeStackArray digits(precision + 1, localStatus); + if (U_FAILURE(localStatus)) { + return ICU_Utility::makeBogusString(); + } for (int32_t i = 0; i < precision; i++) { digits[i] = getDigitPos(precision - i - 1) + '0'; } diff --git a/icu4c/source/i18n/number_utils.cpp b/icu4c/source/i18n/number_utils.cpp index 91d7f335cd8..bef7ea6c61f 100644 --- a/icu4c/source/i18n/number_utils.cpp +++ b/icu4c/source/i18n/number_utils.cpp @@ -258,7 +258,10 @@ void DecNum::toString(ByteSink& output, UErrorCode& status) const { } // "string must be at least dn->digits+14 characters long" int32_t minCapacity = fData.getAlias()->digits + 14; - MaybeStackArray buffer(minCapacity); + MaybeStackArray buffer(minCapacity, status); + if (U_FAILURE(status)) { + return; + } uprv_decNumberToString(fData, buffer.getAlias()); output.Append(buffer.getAlias(), static_cast(uprv_strlen(buffer.getAlias()))); } diff --git a/icu4c/source/i18n/numparse_affixes.cpp b/icu4c/source/i18n/numparse_affixes.cpp index ca293e741d2..cef1685d03c 100644 --- a/icu4c/source/i18n/numparse_affixes.cpp +++ b/icu4c/source/i18n/numparse_affixes.cpp @@ -127,8 +127,8 @@ void AffixPatternMatcherBuilder::addMatcher(NumberParseMatcher& matcher) { fMatchers[fMatchersLen++] = &matcher; } -AffixPatternMatcher AffixPatternMatcherBuilder::build() { - return AffixPatternMatcher(fMatchers, fMatchersLen, fPattern); +AffixPatternMatcher AffixPatternMatcherBuilder::build(UErrorCode& status) { + return AffixPatternMatcher(fMatchers, fMatchersLen, fPattern, status); } AffixTokenMatcherWarehouse::AffixTokenMatcherWarehouse(const AffixTokenMatcherSetupData* setupData) @@ -209,12 +209,13 @@ AffixPatternMatcher AffixPatternMatcher::fromAffixPattern(const UnicodeString& a AffixPatternMatcherBuilder builder(affixPattern, tokenWarehouse, ignorables); AffixUtils::iterateWithConsumer(affixPattern, builder, status); - return builder.build(); + return builder.build(status); } AffixPatternMatcher::AffixPatternMatcher(MatcherArray& matchers, int32_t matchersLen, - const UnicodeString& pattern) - : ArraySeriesMatcher(matchers, matchersLen), fPattern(pattern) {} + const UnicodeString& pattern, UErrorCode& status) + : ArraySeriesMatcher(matchers, matchersLen), fPattern(pattern, status) { +} UnicodeString AffixPatternMatcher::getPattern() const { return fPattern.toAliasedUnicodeString(); @@ -446,28 +447,3 @@ UnicodeString AffixMatcher::toString() const { #endif /* #if !UCONFIG_NO_FORMATTING */ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/icu4c/source/i18n/numparse_affixes.h b/icu4c/source/i18n/numparse_affixes.h index 97a17f4d78c..a82b731ab5b 100644 --- a/icu4c/source/i18n/numparse_affixes.h +++ b/icu4c/source/i18n/numparse_affixes.h @@ -128,7 +128,7 @@ class AffixPatternMatcherBuilder : public TokenConsumer, public MutableMatcherCo void consumeToken(::icu::number::impl::AffixPatternType type, UChar32 cp, UErrorCode& status) override; /** NOTE: You can build only once! */ - AffixPatternMatcher build(); + AffixPatternMatcher build(UErrorCode& status); private: ArraySeriesMatcher::MatcherArray fMatchers; @@ -160,7 +160,8 @@ class U_I18N_API AffixPatternMatcher : public ArraySeriesMatcher { private: CompactUnicodeString<4> fPattern; - AffixPatternMatcher(MatcherArray& matchers, int32_t matchersLen, const UnicodeString& pattern); + AffixPatternMatcher(MatcherArray& matchers, int32_t matchersLen, const UnicodeString& pattern, + UErrorCode& status); friend class AffixPatternMatcherBuilder; }; diff --git a/icu4c/source/i18n/numparse_types.h b/icu4c/source/i18n/numparse_types.h index b4007c2ff5b..a989e021d27 100644 --- a/icu4c/source/i18n/numparse_types.h +++ b/icu4c/source/i18n/numparse_types.h @@ -64,8 +64,9 @@ class CompactUnicodeString { fBuffer[0] = 0; } - CompactUnicodeString(const UnicodeString& text) - : fBuffer(text.length() + 1) { + CompactUnicodeString(const UnicodeString& text, UErrorCode& status) + : fBuffer(text.length() + 1, status) { + if (U_FAILURE(status)) { return; } uprv_memcpy(fBuffer.getAlias(), text.getBuffer(), sizeof(UChar) * text.length()); fBuffer[text.length()] = 0; } diff --git a/icu4c/source/test/intltest/numbertest_parse.cpp b/icu4c/source/test/intltest/numbertest_parse.cpp index 12ecc751bc7..b47519ddb83 100644 --- a/icu4c/source/test/intltest/numbertest_parse.cpp +++ b/icu4c/source/test/intltest/numbertest_parse.cpp @@ -196,7 +196,8 @@ void NumberParserTest::testSeriesMatcher() { PercentMatcher m3(symbols); IgnorablesMatcher m4(0); - ArraySeriesMatcher::MatcherArray matchers(5); + ArraySeriesMatcher::MatcherArray matchers(5, status); + status.assertSuccess(); matchers[0] = &m0; matchers[1] = &m1; matchers[2] = &m2;