Skip to content

Commit

Permalink
ICU-22983 Fix DecimalQuantity::shiftLeft ubsan issue
Browse files Browse the repository at this point in the history
ICU-22983 Add java tests and comments
  • Loading branch information
FrankYFTang committed Nov 28, 2024
1 parent 2ba362f commit e025466
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 2 deletions.
2 changes: 1 addition & 1 deletion icu4c/source/i18n/number_decimalquantity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1133,7 +1133,7 @@ void DecimalQuantity::setDigitPos(int32_t position, int8_t value) {
}

void DecimalQuantity::shiftLeft(int32_t numDigits) {
if (!usingBytes && precision + numDigits > 16) {
if (!usingBytes && precision + numDigits >= 16) {
switchStorage();
}
if (usingBytes) {
Expand Down
5 changes: 5 additions & 0 deletions icu4c/source/test/intltest/numfmtst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &n
TESTCASE_AUTO(Test10997_FormatCurrency);
TESTCASE_AUTO(Test21556_CurrencyAsDecimal);
TESTCASE_AUTO(Test22088_Ethiopic);
TESTCASE_AUTO(Test22983_LongFraction);
TESTCASE_AUTO_END;
}

Expand Down Expand Up @@ -10161,5 +10162,9 @@ void NumberFormatTest::Test22088_Ethiopic() {
assertEquals("Wrong result with UNUM_NUMBERING_SYSTEM and English", u"123", nf3->format(123, result));
}
}
void NumberFormatTest::Test22983_LongFraction() {
IcuTestErrorCode status(*this, "Test22983_LongFraction");
DecimalFormat df(u"0.0000000000000001", status);
}

#endif /* #if !UCONFIG_NO_FORMATTING */
1 change: 1 addition & 0 deletions icu4c/source/test/intltest/numfmtst.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ class NumberFormatTest: public CalendarTimeZoneTest {
void Test10997_FormatCurrency();
void Test21556_CurrencyAsDecimal();
void Test22088_Ethiopic();
void Test22983_LongFraction();

private:
UBool testFormattableAsUFormattable(const char *file, int line, Formattable &f);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1835,6 +1835,11 @@ public void test4241880() {
}
Locale.setDefault(savedLocale);
}

@Test
public void test22983LongFraction() {
DecimalFormat format = new DecimalFormat("0.0000000000000001");
}
}

class myformat implements Serializable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,14 @@ protected void setDigitPos(int position, byte value) {

@Override
protected void shiftLeft(int numDigits) {
if (!usingBytes && precision + numDigits > 16) {
// https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.19
// If the promoted type of the left-hand operand is long, then only the
// six lowest-order bits of the right-hand operand are used as the shift
// distance. It is as if the right-hand operand were subjected to a bitwise
// logical AND operator & (§15.22.1) with the mask value 0x3f (0b111111).
// The shift distance actually used is therefore always in the range 0 to
// 63, inclusive.
if (!usingBytes && precision + numDigits >= 16) {
switchStorage();
}
if (usingBytes) {
Expand Down

0 comments on commit e025466

Please sign in to comment.