diff --git a/icu4c/source/common/putil.cpp b/icu4c/source/common/putil.cpp index ea15fdff0b0c..31ec64df20cf 100644 --- a/icu4c/source/common/putil.cpp +++ b/icu4c/source/common/putil.cpp @@ -915,8 +915,15 @@ static UBool compareBinaryFiles(const char* defaultTZFileName, const char* TZFil fseek(tzInfo->defaultTZFilePtr, 0, SEEK_END); tzInfo->defaultTZFileSize = ftell(tzInfo->defaultTZFilePtr); } - fseek(file, 0, SEEK_END); + if (fseek(file, 0, SEEK_END) != 0) { + fclose(file); + return false; + } sizeFile = ftell(file); + if (sizeFile == -1) { + fclose(file); + return false; + } sizeFileLeft = sizeFile; if (sizeFile != tzInfo->defaultTZFileSize) { @@ -926,16 +933,26 @@ static UBool compareBinaryFiles(const char* defaultTZFileName, const char* TZFil * compare each byte to determine equality. */ if (tzInfo->defaultTZBuffer == nullptr) { - rewind(tzInfo->defaultTZFilePtr); + if (fseek(tzInfo->defaultTZFilePtr, 0, SEEK_SET) != 0) { + fclose(file); + return false; + } tzInfo->defaultTZBuffer = static_cast(uprv_malloc(sizeof(char) * tzInfo->defaultTZFileSize)); sizeFileRead = fread(tzInfo->defaultTZBuffer, 1, tzInfo->defaultTZFileSize, tzInfo->defaultTZFilePtr); } - rewind(file); + if (fseek(file, 0, SEEK_SET) != 0) { + fclose(file); + return false; + } while(sizeFileLeft > 0) { uprv_memset(bufferFile, 0, MAX_READ_SIZE); sizeFileToRead = sizeFileLeft < MAX_READ_SIZE ? sizeFileLeft : MAX_READ_SIZE; sizeFileRead = fread(bufferFile, 1, sizeFileToRead, file); + if (sizeFileRead == -1) { + fclose(file); + return false; + } if (memcmp(tzInfo->defaultTZBuffer + tzInfo->defaultTZPosition, bufferFile, sizeFileRead) != 0) { result = false; break; diff --git a/icu4c/source/common/ucnv.cpp b/icu4c/source/common/ucnv.cpp index c7926d2ea717..c6c5084a7840 100644 --- a/icu4c/source/common/ucnv.cpp +++ b/icu4c/source/common/ucnv.cpp @@ -877,6 +877,10 @@ _fromUnicodeWithCallback(UConverterFromUnicodeArgs *pArgs, UErrorCode *err) { * and failed to consume all of them. * We need to "replay" them from a temporary buffer and convert them first. */ + if (!pArgs->source) { + *err=U_ILLEGAL_ARGUMENT_ERROR; + return; + } realSource=pArgs->source; realSourceLimit=pArgs->sourceLimit; realFlush=pArgs->flush; @@ -1322,6 +1326,10 @@ _toUnicodeWithCallback(UConverterToUnicodeArgs *pArgs, UErrorCode *err) { * and failed to consume all of them. * We need to "replay" them from a temporary buffer and convert them first. */ + if (!pArgs->source) { + *err=U_ILLEGAL_ARGUMENT_ERROR; + return; + } realSource=pArgs->source; realSourceLimit=pArgs->sourceLimit; realFlush=pArgs->flush; diff --git a/icu4c/source/common/udata.cpp b/icu4c/source/common/udata.cpp index b9b737f177ed..7d5de2c09768 100644 --- a/icu4c/source/common/udata.cpp +++ b/icu4c/source/common/udata.cpp @@ -1291,7 +1291,7 @@ doOpenChoice(const char *path, const char *type, const char *name, dataPath = u_getDataDirectory(); /**** Time zone individual files override */ - if (isICUData && isTimeZoneFile(name, type)) { + if (isICUData && type != nullptr && isTimeZoneFile(name, type)) { const char *tzFilesDir = u_getTimeZoneFilesDirectory(pErrorCode); if (tzFilesDir[0] != 0) { #ifdef UDATA_DEBUG diff --git a/icu4c/source/common/uenum.cpp b/icu4c/source/common/uenum.cpp index b4a5071ae7bc..0e96318da481 100644 --- a/icu4c/source/common/uenum.cpp +++ b/icu4c/source/common/uenum.cpp @@ -99,7 +99,8 @@ uenum_unextDefault(UEnumeration* en, if (ustr == nullptr) { *status = U_MEMORY_ALLOCATION_ERROR; } else { - u_charsToUChars(cstr, ustr, len+1); + u_charsToUChars(cstr, ustr, len); + ustr[len] = 0; } } } else { @@ -129,7 +130,8 @@ uenum_nextDefault(UEnumeration* en, *status = U_MEMORY_ALLOCATION_ERROR; return nullptr; } - u_UCharsToChars(tempUCharVal, tempCharVal, *resultLength + 1); + u_UCharsToChars(tempUCharVal, tempCharVal, *resultLength); + tempCharVal[*resultLength] = 0; return tempCharVal; } else { *status = U_UNSUPPORTED_ERROR; diff --git a/icu4c/source/common/uidna.cpp b/icu4c/source/common/uidna.cpp index b47edefe1167..04c5c2e4cd7f 100644 --- a/icu4c/source/common/uidna.cpp +++ b/icu4c/source/common/uidna.cpp @@ -915,6 +915,7 @@ uidna_compare( const char16_t *s1, int32_t length1, if (U_FAILURE(bufferStatus)) { *status = bufferStatus; + goto CLEANUP; } // when toASCII is applied all label separators are replaced with FULL_STOP diff --git a/icu4c/source/common/uniset.cpp b/icu4c/source/common/uniset.cpp index 0a63dad9dd0f..5eb53d060ea8 100644 --- a/icu4c/source/common/uniset.cpp +++ b/icu4c/source/common/uniset.cpp @@ -241,7 +241,7 @@ UnicodeSet& UnicodeSet::copyFrom(const UnicodeSet& o, UBool asThawed) { } else if (hasStrings()) { strings_->removeAllElements(); } - if (o.stringSpan != nullptr && !asThawed) { + if (o.stringSpan != nullptr && strings_ != nullptr && !asThawed) { stringSpan = new UnicodeSetStringSpan(*o.stringSpan, *strings_); if (stringSpan == nullptr) { // Check for memory allocation error. setToBogus(); diff --git a/icu4c/source/common/ushape.cpp b/icu4c/source/common/ushape.cpp index b7946dc3ce03..a50b814846e0 100644 --- a/icu4c/source/common/ushape.cpp +++ b/icu4c/source/common/ushape.cpp @@ -982,7 +982,7 @@ expandCompositCharAtEnd(char16_t *dest, int32_t sourceLength, int32_t destSize,U uprv_memset(tempbuffer, 0, (sourceLength+1)*U_SIZEOF_UCHAR); - while(dest[inpsize-1] == SPACE_CHAR) { + while(inpsize>0 && dest[inpsize-1] == SPACE_CHAR) { countr++; inpsize--; } @@ -1525,6 +1525,11 @@ u_shapeArabic(const char16_t *source, int32_t sourceLength, prevLink = currLink; currLink = getLink(source[i]); if (aggregate_tashkeel && ((prevLink|currLink)&COMBINE) == COMBINE && aggregation_possible) { + if (j<0 || j>=2*sourceLength) { + *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; + if (tempsource != nullptr) uprv_free(tempsource); + return 0; + } aggregation_possible = 0; tempsource[j] = (prev 0); + if (totalLength <= 0) { + errorCode = U_ILLEGAL_ARGUMENT_ERROR; + return; + } if(totalLength <= reorderCodesCapacity) { ownedCodes = const_cast(reorderCodes); } else { diff --git a/icu4c/source/i18n/nfrs.cpp b/icu4c/source/i18n/nfrs.cpp index 75b279cccef4..253ae4d683a8 100644 --- a/icu4c/source/i18n/nfrs.cpp +++ b/icu4c/source/i18n/nfrs.cpp @@ -602,6 +602,9 @@ NFRuleSet::findFractionRuleSetRule(double number) const // all the precision we need, and we can do all of the rest // of the math using integer arithmetic int64_t leastCommonMultiple = rules[0]->getBaseValue(); + if (leastCommonMultiple == 0) { + return nullptr; + } int64_t numerator; { for (uint32_t i = 1; i < rules.size(); ++i) { diff --git a/icu4c/source/i18n/nfrule.cpp b/icu4c/source/i18n/nfrule.cpp index 26a6e818d5a9..a970c07b7818 100644 --- a/icu4c/source/i18n/nfrule.cpp +++ b/icu4c/source/i18n/nfrule.cpp @@ -903,7 +903,8 @@ NFRule::shouldRollBack(int64_t number) const // a modulus substitution, its base value isn't an even multiple // of 100, and the value we're trying to format _is_ an even // multiple of 100. This is called the "rollback rule." - if ((sub1 != nullptr && sub1->isModulusSubstitution()) || (sub2 != nullptr && sub2->isModulusSubstitution())) { + if (radix != 0 && ((sub1 != nullptr && sub1->isModulusSubstitution()) || + (sub2 != nullptr && sub2->isModulusSubstitution()))) { int64_t re = util64_pow(radix, exponent); return (number % re) == 0 && (baseValue % re) != 0; } diff --git a/icu4c/source/i18n/number_capi.cpp b/icu4c/source/i18n/number_capi.cpp index a35680a62003..e9d44412e446 100644 --- a/icu4c/source/i18n/number_capi.cpp +++ b/icu4c/source/i18n/number_capi.cpp @@ -380,6 +380,9 @@ usnumf_formatInt64( return; } auto localResult = formatter->fFormatter.formatInt64(value, *ec); + if (U_FAILURE(*ec)) { + return; + } result->setTo(std::move(localResult)); } diff --git a/icu4c/source/i18n/scriptset.cpp b/icu4c/source/i18n/scriptset.cpp index 2bdb32d6fead..91801cfedef8 100644 --- a/icu4c/source/i18n/scriptset.cpp +++ b/icu4c/source/i18n/scriptset.cpp @@ -225,9 +225,8 @@ ScriptSet &ScriptSet::parseScripts(const UnicodeString &scriptString, UErrorCode } } if (oneScriptName.length() > 0) { - char buf[40]; + char buf[40] = {}; oneScriptName.extract(0, oneScriptName.length(), buf, sizeof(buf)-1, US_INV); - buf[sizeof(buf)-1] = 0; int32_t sc = u_getPropertyValueEnum(UCHAR_SCRIPT, buf); if (sc == UCHAR_INVALID_CODE) { status = U_ILLEGAL_ARGUMENT_ERROR; diff --git a/icu4c/source/i18n/timezone.cpp b/icu4c/source/i18n/timezone.cpp index 8028c4ecf5cb..c7f09751daa0 100644 --- a/icu4c/source/i18n/timezone.cpp +++ b/icu4c/source/i18n/timezone.cpp @@ -739,7 +739,9 @@ void TimeZone::getOffset(UDate date, UBool local, int32_t& rawOffset, static_cast(dow), millis, Grego::monthLength(year, month), ec) - rawOffset; - + if (U_FAILURE(ec)) { + return; + } // Recompute if local==true, dstOffset!=0. if (pass!=0 || !local || dstOffset == 0) { break; diff --git a/icu4c/source/i18n/tzfmt.cpp b/icu4c/source/i18n/tzfmt.cpp index aaec9f31c42e..9831c5294e5d 100644 --- a/icu4c/source/i18n/tzfmt.cpp +++ b/icu4c/source/i18n/tzfmt.cpp @@ -697,8 +697,8 @@ TimeZoneFormat::format(UTimeZoneFormatStyle style, const TimeZone& tz, UDate dat UErrorCode status = U_ZERO_ERROR; int32_t rawOffset, dstOffset; tz.getOffset(date, false, rawOffset, dstOffset, status); - int32_t offset = rawOffset + dstOffset; if (U_SUCCESS(status)) { + int32_t offset = rawOffset + dstOffset; switch (style) { case UTZFMT_STYLE_GENERIC_LOCATION: case UTZFMT_STYLE_GENERIC_LONG: diff --git a/icu4c/source/i18n/ucol_sit.cpp b/icu4c/source/i18n/ucol_sit.cpp index f8fa02fad719..bca901c08432 100644 --- a/icu4c/source/i18n/ucol_sit.cpp +++ b/icu4c/source/i18n/ucol_sit.cpp @@ -578,7 +578,10 @@ ucol_normalizeShortDefinitionString(const char *definition, if(U_FAILURE(*status)) { return 0; } - + if(!destination && capacity != 0) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } if(destination) { uprv_memset(destination, 0, capacity*sizeof(char)); } diff --git a/icu4c/source/i18n/uregex.cpp b/icu4c/source/i18n/uregex.cpp index 5a5ff1d0387d..54f103aa9f95 100644 --- a/icu4c/source/i18n/uregex.cpp +++ b/icu4c/source/i18n/uregex.cpp @@ -1877,7 +1877,7 @@ int32_t RegexCImpl::split(RegularExpression *regexp, i++; // Set up to extract the capture group contents into the dest buffer. - destFields[i] = &destBuf[destIdx]; + destFields[i] = (destBuf == nullptr) ? nullptr : &destBuf[destIdx]; tStatus = U_ZERO_ERROR; int32_t t = uregex_group(reinterpret_cast(regexp), groupNum,