From 278b9cb73536d980bbac35becf80a0de5a7d5be3 Mon Sep 17 00:00:00 2001 From: Andy Heninger Date: Mon, 20 Aug 2018 16:40:46 -0700 Subject: [PATCH] ICU-20079 integer overflow & divide by zero sanitizer fixes. (#67) --- icu4c/source/common/bytestriebuilder.cpp | 3 ++- icu4c/source/common/uniset.cpp | 6 +++--- icu4c/source/common/usprep.cpp | 4 +++- icu4c/source/io/ufmt_cmn.cpp | 4 ++-- icu4c/source/test/intltest/numrgts.cpp | 19 ++++++++++--------- icu4c/source/test/iotest/iotest.cpp | 6 +++--- 6 files changed, 23 insertions(+), 19 deletions(-) diff --git a/icu4c/source/common/bytestriebuilder.cpp b/icu4c/source/common/bytestriebuilder.cpp index 581505e009..ec1ab7d8f5 100644 --- a/icu4c/source/common/bytestriebuilder.cpp +++ b/icu4c/source/common/bytestriebuilder.cpp @@ -339,7 +339,8 @@ BytesTrieBuilder::indexOfElementWithNextUnit(int32_t i, int32_t byteIndex, UChar BytesTrieBuilder::BTLinearMatchNode::BTLinearMatchNode(const char *bytes, int32_t len, Node *nextNode) : LinearMatchNode(len, nextNode), s(bytes) { - hash=hash*37+ustr_hashCharsN(bytes, len); + hash=static_cast( + static_cast(hash)*37u + static_cast(ustr_hashCharsN(bytes, len))); } UBool diff --git a/icu4c/source/common/uniset.cpp b/icu4c/source/common/uniset.cpp index 74a9efe47d..7206e63e88 100644 --- a/icu4c/source/common/uniset.cpp +++ b/icu4c/source/common/uniset.cpp @@ -364,12 +364,12 @@ UBool UnicodeSet::operator==(const UnicodeSet& o) const { * @see Object#hashCode() */ int32_t UnicodeSet::hashCode(void) const { - int32_t result = len; + uint32_t result = static_cast(len); for (int32_t i = 0; i < len; ++i) { - result *= 1000003; + result *= 1000003u; result += list[i]; } - return result; + return static_cast(result); } //---------------------------------------------------------------- diff --git a/icu4c/source/common/usprep.cpp b/icu4c/source/common/usprep.cpp index 1af1d07490..01238b35f5 100644 --- a/icu4c/source/common/usprep.cpp +++ b/icu4c/source/common/usprep.cpp @@ -112,7 +112,9 @@ hashEntry(const UHashTok parm) { UHashTok namekey, pathkey; namekey.pointer = b->name; pathkey.pointer = b->path; - return uhash_hashChars(namekey)+37*uhash_hashChars(pathkey); + uint32_t unsignedHash = static_cast(uhash_hashChars(namekey)) + + 37u * static_cast(uhash_hashChars(pathkey)); + return static_cast(unsignedHash); } /* compares two entries */ diff --git a/icu4c/source/io/ufmt_cmn.cpp b/icu4c/source/io/ufmt_cmn.cpp index 2b1a76fc8a..c539729b87 100644 --- a/icu4c/source/io/ufmt_cmn.cpp +++ b/icu4c/source/io/ufmt_cmn.cpp @@ -140,7 +140,7 @@ ufmt_uto64(const UChar *buffer, { const UChar *limit; int32_t count; - int64_t result; + uint64_t result; /* intialize parameters */ @@ -160,7 +160,7 @@ ufmt_uto64(const UChar *buffer, } *len = count; - return result; + return static_cast(result); } #define NIBBLE_PER_BYTE 2 diff --git a/icu4c/source/test/intltest/numrgts.cpp b/icu4c/source/test/intltest/numrgts.cpp index 482704537d..1870765ae8 100644 --- a/icu4c/source/test/intltest/numrgts.cpp +++ b/icu4c/source/test/intltest/numrgts.cpp @@ -11,6 +11,7 @@ #include "numrgts.h" +#include // std::signbit #include // DBL_MIN, DBL_MAX #include @@ -2142,8 +2143,9 @@ NumberFormatRegressionTest::Test4162852(void) { UErrorCode status = U_ZERO_ERROR; for(int32_t i=0; i < 2; ++i) { - NumberFormat *f = (i == 0) ? NumberFormat::createInstance(status) - : NumberFormat::createPercentInstance(status); + LocalPointer f( + ((i == 0) ? NumberFormat::createInstance(status) : NumberFormat::createPercentInstance(status)), + status); if(U_FAILURE(status)) { dataerrln("Couldn't create number format - %s", u_errorName(status)); return; @@ -2154,20 +2156,19 @@ NumberFormatRegressionTest::Test4162852(void) f->format(d, s); Formattable n; f->parse(s, n, status); - if(U_FAILURE(status)) + if(U_FAILURE(status)) { errln("Couldn't parse!"); + return; + } double e = n.getDouble(); - logln(UnicodeString("") + - d + " -> " + - '"' + s + '"' + " -> " + e); + logln("%f -> \"%s\" -> %f", d, CStr(s)(), e); #if (U_PLATFORM == U_PF_OS390 && !defined(IEEE_754)) || U_PLATFORM == U_PF_OS400 if (e != 0.0) { #else - if (e != 0.0 || 1.0/e > 0.0) { + if (e != 0.0 || (std::signbit(e) == false)) { #endif - logln("Failed to parse negative zero"); + errln("Failed to parse negative zero"); } - delete f; } } diff --git a/icu4c/source/test/iotest/iotest.cpp b/icu4c/source/test/iotest/iotest.cpp index 6bc549ad4d..186d10e17e 100644 --- a/icu4c/source/test/iotest/iotest.cpp +++ b/icu4c/source/test/iotest/iotest.cpp @@ -178,18 +178,18 @@ char* DataDrivenLogger::fgTestDataPath = NULL; static int64_t uto64(const UChar *buffer) { - int64_t result = 0; + uint64_t result = 0; /* iterate through buffer */ while(*buffer) { /* read the next digit */ - result *= 16; + result *= 16u; if (!u_isxdigit(*buffer)) { log_err("\\u%04X is not a valid hex digit for this test\n", (UChar)*buffer); } result += *buffer - 0x0030 - (*buffer >= 0x0041 ? (*buffer >= 0x0061 ? 39 : 7) : 0); buffer++; } - return result; + return (int64_t)result; } #endif