diff --git a/icu4c/source/common/filteredbrk.cpp b/icu4c/source/common/filteredbrk.cpp index 29b02dd38424..a7ac66e7a2d4 100644 --- a/icu4c/source/common/filteredbrk.cpp +++ b/icu4c/source/common/filteredbrk.cpp @@ -603,7 +603,11 @@ SimpleFilteredBreakIteratorBuilder::build(BreakIterator* adoptBreakIterator, UEr LocalArray ustrs(ustrs_ptr); LocalMemory partials; - partials.allocateInsteadAndReset(subCount); + // Check subCount > 0 to distinguish allocation failure from empty set (both return nullptr) + if (subCount > 0 && partials.allocateInsteadAndReset(subCount) == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } LocalPointer backwardsTrie; // i.e. ".srM" for Mrs. LocalPointer forwardsPartialTrie; // Has ".a" for "a.M." diff --git a/icu4c/source/common/loclikelysubtags.cpp b/icu4c/source/common/loclikelysubtags.cpp index b37aaeec718e..fb2e43f9d91d 100644 --- a/icu4c/source/common/loclikelysubtags.cpp +++ b/icu4c/source/common/loclikelysubtags.cpp @@ -534,7 +534,10 @@ LSR LikelySubtags::makeMaximizedLsrFrom(const Locale &locale, } LSR max = makeMaximizedLsr(locale.getLanguage(), locale.getScript(), locale.getCountry(), locale.getVariant(), returnInputIfUnmatch, errorCode); - + if (!U_SUCCESS(errorCode)) { + return LSR(name, "", "", LSR::EXPLICIT_LSR); + } + if (uprv_strlen(max.language) == 0 && uprv_strlen(max.script) == 0 && uprv_strlen(max.region) == 0) { diff --git a/icu4c/source/common/normalizer2impl.cpp b/icu4c/source/common/normalizer2impl.cpp index eb8ed31553c4..99882e6098f1 100644 --- a/icu4c/source/common/normalizer2impl.cpp +++ b/icu4c/source/common/normalizer2impl.cpp @@ -533,6 +533,10 @@ Normalizer2Impl::copyLowPrefixFromNulTerminated(const char16_t *src, // data and check the first part of the string. // After this prefix, determine the string length to simplify the rest // of the code. + if(src==nullptr) { + errorCode=U_ILLEGAL_ARGUMENT_ERROR; + return src; + } const char16_t *prevSrc=src; char16_t c; while((c=*src++)paraLevel is ok even if contextual multiple paragraphs. */ if(pBiDi->paraLevelconverter; s=pArgs->source; @@ -891,6 +892,7 @@ _fromUnicodeWithCallback(UConverterFromUnicodeArgs *pArgs, UErrorCode *err) { pArgs->sourceLimit=replay-cnv->preFromULength; pArgs->flush=false; sourceIndex=-1; + needRestore=true; cnv->preFromULength=0; } @@ -982,6 +984,7 @@ _fromUnicodeWithCallback(UConverterFromUnicodeArgs *pArgs, UErrorCode *err) { if((sourceIndex+=cnv->preFromULength)<0) { sourceIndex=-1; } + needRestore=true; cnv->preFromULength=0; } else { @@ -1002,7 +1005,7 @@ _fromUnicodeWithCallback(UConverterFromUnicodeArgs *pArgs, UErrorCode *err) { * (continue converting by breaking out of only the inner loop) */ break; - } else if(realSource!=nullptr) { + } else if(needRestore) { /* switch back from replaying to the real source and continue */ pArgs->source=realSource; pArgs->sourceLimit=realSourceLimit; @@ -1010,6 +1013,7 @@ _fromUnicodeWithCallback(UConverterFromUnicodeArgs *pArgs, UErrorCode *err) { sourceIndex=realSourceIndex; realSource=nullptr; + needRestore=false; break; } else if(pArgs->flush && cnv->fromUChar32!=0) { /* @@ -1065,7 +1069,7 @@ _fromUnicodeWithCallback(UConverterFromUnicodeArgs *pArgs, UErrorCode *err) { * copied back into the UConverter * and the real arguments must be restored */ - if(realSource!=nullptr) { + if(needRestore) { int32_t length; U_ASSERT(cnv->preFromULength==0); @@ -1079,6 +1083,7 @@ _fromUnicodeWithCallback(UConverterFromUnicodeArgs *pArgs, UErrorCode *err) { pArgs->source=realSource; pArgs->sourceLimit=realSourceLimit; pArgs->flush=realFlush; + needRestore=false; } return; diff --git a/icu4c/source/common/ucnv2022.cpp b/icu4c/source/common/ucnv2022.cpp index df6f0cb9ba6d..34e4bf4bbc77 100644 --- a/icu4c/source/common/ucnv2022.cpp +++ b/icu4c/source/common/ucnv2022.cpp @@ -178,13 +178,18 @@ enum { MAX_JA_VERSION=0 }; #else enum { MAX_JA_VERSION=4 }; #endif -static const uint16_t jpCharsetMasks[MAX_JA_VERSION+1]={ +static const uint16_t jpCharsetMasks[5]={ CSM(ASCII)|CSM(JISX201)|CSM(JISX208)|CSM(HWKANA_7BIT), #if !UCONFIG_ONLY_HTML_CONVERSION CSM(ASCII)|CSM(JISX201)|CSM(JISX208)|CSM(HWKANA_7BIT)|CSM(JISX212), CSM(ASCII)|CSM(JISX201)|CSM(JISX208)|CSM(HWKANA_7BIT)|CSM(JISX212)|CSM(GB2312)|CSM(KSC5601)|CSM(ISO8859_1)|CSM(ISO8859_7), CSM(ASCII)|CSM(JISX201)|CSM(JISX208)|CSM(HWKANA_7BIT)|CSM(JISX212)|CSM(GB2312)|CSM(KSC5601)|CSM(ISO8859_1)|CSM(ISO8859_7), CSM(ASCII)|CSM(JISX201)|CSM(JISX208)|CSM(HWKANA_7BIT)|CSM(JISX212)|CSM(GB2312)|CSM(KSC5601)|CSM(ISO8859_1)|CSM(ISO8859_7) +#else + CSM(ASCII)|CSM(JISX201)|CSM(JISX208)|CSM(HWKANA_7BIT), + CSM(ASCII)|CSM(JISX201)|CSM(JISX208)|CSM(HWKANA_7BIT), + CSM(ASCII)|CSM(JISX201)|CSM(JISX208)|CSM(HWKANA_7BIT), + CSM(ASCII)|CSM(JISX201)|CSM(JISX208)|CSM(HWKANA_7BIT) #endif }; diff --git a/icu4c/source/common/unames.cpp b/icu4c/source/common/unames.cpp index 71b2baff6c19..60b0de4f4e8d 100644 --- a/icu4c/source/common/unames.cpp +++ b/icu4c/source/common/unames.cpp @@ -999,6 +999,11 @@ enumAlgNames(AlgorithmicRange *range, uint16_t prefixLength, i, idx; char c; + + /* guard against invalid data */ + if(count==0 || count>8) { + return true; + } /* name = prefix factorized-elements */ @@ -1025,7 +1030,7 @@ enumAlgNames(AlgorithmicRange *range, while(++start0) { idx = static_cast(indexes[--i] + 1); if(idx8) { + return true; + } + /* name = prefix factorized-elements */ /* compare prefix */ @@ -1154,7 +1164,7 @@ findAlgName(AlgorithmicRange *range, UCharNameChoice nameChoice, const char *oth while(++start0) { idx = static_cast(indexes[--i] + 1); if(idx=capacity) { i-=capacity; @@ -107,6 +111,10 @@ class OffsetList { // Only ever stack-allocated, does not need to inherit UMemo // Add an offset. The list must not contain it yet. // offset=[1..maxLength] void addOffset(int32_t offset) { + // If OffsetList has zero capacity due to setMaxLength memory allocation error. + if (capacity == 0) { + return; + } int32_t i=start+offset; if(i>=capacity) { i-=capacity; @@ -117,6 +125,10 @@ class OffsetList { // Only ever stack-allocated, does not need to inherit UMemo // offset=[1..maxLength] UBool containsOffset(int32_t offset) const { + // If OffsetList has zero capacity due to setMaxLength memory allocation error. + if (capacity == 0) { + return false; + } int32_t i=start+offset; if(i>=capacity) { i-=capacity; @@ -128,6 +140,10 @@ class OffsetList { // Only ever stack-allocated, does not need to inherit UMemo // and reduce all other offsets by this minimum. // Returns [1..maxLength]. int32_t popMinimum() { + // If OffsetList has zero capacity due to setMaxLength memory allocation error. + if (capacity == 0) { + return 0; + } // Look for the next offset in list[start+1..capacity-1]. int32_t i=start, result; while(++i(weight & (0xffffffff << (8 * (4 - length)))); } diff --git a/icu4c/source/i18n/nfrs.cpp b/icu4c/source/i18n/nfrs.cpp index b063f7b6d816..9c75da3c31e5 100644 --- a/icu4c/source/i18n/nfrs.cpp +++ b/icu4c/source/i18n/nfrs.cpp @@ -604,8 +604,14 @@ NFRuleSet::findFractionRuleSetRule(double number) const int64_t numerator; { for (uint32_t i = 1; i < rules.size(); ++i) { + if (leastCommonMultiple == 0) { + return nullptr; + } leastCommonMultiple = util_lcm(leastCommonMultiple, rules[i]->getBaseValue()); } + if (leastCommonMultiple == 0) { + return nullptr; + } numerator = util64_fromDouble(number * static_cast(leastCommonMultiple) + 0.5); } // for each rule, do the following... diff --git a/icu4c/source/i18n/rbt_pars.cpp b/icu4c/source/i18n/rbt_pars.cpp index e2dbb058d5c5..36ec25dc8be7 100644 --- a/icu4c/source/i18n/rbt_pars.cpp +++ b/icu4c/source/i18n/rbt_pars.cpp @@ -1496,6 +1496,13 @@ int32_t TransliteratorParser::syntaxError(UErrorCode parseErrorCode, int32_t pos, UErrorCode& status) { + if (pos > rule.length()) { + pos = rule.length(); + } + if (pos < 0) { + pos = 0; + } + parseError.offset = pos; parseError.line = 0 ; /* we are not using line numbers */ diff --git a/icu4c/source/i18n/stsearch.cpp b/icu4c/source/i18n/stsearch.cpp index c41e8de21dc1..e7e4f32dcbe2 100644 --- a/icu4c/source/i18n/stsearch.cpp +++ b/icu4c/source/i18n/stsearch.cpp @@ -290,6 +290,9 @@ StringSearch * StringSearch::safeClone() const getCollator(), m_breakiterator_, status); + if (U_FAILURE(status)) { + return nullptr; + } /* test for nullptr */ if (result == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; diff --git a/icu4c/source/i18n/tridpars.cpp b/icu4c/source/i18n/tridpars.cpp index 5c769dc39fbc..31eff2af0dce 100644 --- a/icu4c/source/i18n/tridpars.cpp +++ b/icu4c/source/i18n/tridpars.cpp @@ -907,6 +907,9 @@ void U_CALLCONV TransliteratorIDParser::init(UErrorCode &status) { ucln_i18n_registerCleanup(UCLN_I18N_TRANSLITERATOR, utrans_transliterator_cleanup); SPECIAL_INVERSES = new Hashtable(true, status); + if (U_FAILURE(status)) { + return; + } if (SPECIAL_INVERSES == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; return;