mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-14 17:24:01 +00:00
ICU-13634 Fixing some clang sanitizer issues, including one potentially serious one deep inside DecimalQuantity.
X-SVN-Rev: 41245
This commit is contained in:
parent
efa58f5d80
commit
55080e2804
5 changed files with 52 additions and 17 deletions
|
@ -837,7 +837,7 @@ UnicodeString DecimalQuantity::toScientificString() const {
|
|||
|
||||
int8_t DecimalQuantity::getDigitPos(int32_t position) const {
|
||||
if (usingBytes) {
|
||||
if (position < 0 || position > precision) { return 0; }
|
||||
if (position < 0 || position >= precision) { return 0; }
|
||||
return fBCD.bcdBytes.ptr[position];
|
||||
} else {
|
||||
if (position < 0 || position >= 16) { return 0; }
|
||||
|
|
|
@ -143,7 +143,7 @@ static void strToInt(
|
|||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return;
|
||||
}
|
||||
int32_t value = 0;
|
||||
uint32_t value = 0;
|
||||
for (int32_t i = start; i < len; ++i) {
|
||||
UChar ch = str[i];
|
||||
if (ch < 0x30 || ch > 0x39) {
|
||||
|
@ -152,25 +152,23 @@ static void strToInt(
|
|||
}
|
||||
value = value * 10 - 0x30 + (int32_t) ch;
|
||||
}
|
||||
if (neg) {
|
||||
value = -value;
|
||||
}
|
||||
*static_cast<int32_t *>(intPtr) = value;
|
||||
int32_t signedValue = neg ? -value : static_cast<int32_t>(value);
|
||||
*static_cast<int32_t *>(intPtr) = signedValue;
|
||||
}
|
||||
|
||||
static void intToStr(
|
||||
const void *intPtr, UnicodeString &appendTo) {
|
||||
UChar buffer[20];
|
||||
int32_t x = *static_cast<const int32_t *>(intPtr);
|
||||
UBool neg = FALSE;
|
||||
if (x < 0) {
|
||||
neg = TRUE;
|
||||
x = -x;
|
||||
}
|
||||
if (neg) {
|
||||
// int64_t such that all int32_t values can be negated
|
||||
int64_t xSigned = *static_cast<const int32_t *>(intPtr);
|
||||
uint32_t x;
|
||||
if (xSigned < 0) {
|
||||
appendTo.append((UChar)0x2D);
|
||||
x = static_cast<uint32_t>(-xSigned);
|
||||
} else {
|
||||
x = static_cast<uint32_t>(xSigned);
|
||||
}
|
||||
int32_t len = uprv_itou(buffer, UPRV_LENGTHOF(buffer), (uint32_t) x, 10, 1);
|
||||
int32_t len = uprv_itou(buffer, UPRV_LENGTHOF(buffer), x, 10, 1);
|
||||
appendTo.append(buffer, 0, len);
|
||||
}
|
||||
|
||||
|
|
|
@ -2047,9 +2047,23 @@ void NumberFormatterApiTest::locale() {
|
|||
void NumberFormatterApiTest::formatTypes() {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
LocalizedNumberFormatter formatter = NumberFormatter::withLocale(Locale::getEnglish());
|
||||
const char* str1 = "98765432123456789E1";
|
||||
UnicodeString actual = formatter.formatDecimal(str1, status).toString();
|
||||
|
||||
// Double
|
||||
assertEquals("Format double", "514.23", formatter.formatDouble(514.23, status).toString());
|
||||
|
||||
// Int64
|
||||
assertEquals("Format int64", "51,423", formatter.formatDouble(51423L, status).toString());
|
||||
|
||||
// decNumber
|
||||
UnicodeString actual = formatter.formatDecimal("98765432123456789E1", status).toString();
|
||||
assertEquals("Format decNumber", u"987,654,321,234,567,890", actual);
|
||||
|
||||
// Also test proper DecimalQuantity bytes storage when all digits are in the fraction.
|
||||
// The number needs to have exactly 40 digits, which is the size of the default buffer.
|
||||
// (issue discovered by the address sanitizer in C++)
|
||||
static const char* str = "0.009876543210987654321098765432109876543211";
|
||||
actual = formatter.rounding(Rounder::unlimited()).formatDecimal(str, status).toString();
|
||||
assertEquals("Format decNumber to 40 digits", str, actual);
|
||||
}
|
||||
|
||||
void NumberFormatterApiTest::errors() {
|
||||
|
|
|
@ -90,7 +90,7 @@ public final class DecimalQuantity_DualStorageBCD extends DecimalQuantity_Abstra
|
|||
@Override
|
||||
protected byte getDigitPos(int position) {
|
||||
if (usingBytes) {
|
||||
if (position < 0 || position > precision)
|
||||
if (position < 0 || position >= precision)
|
||||
return 0;
|
||||
return bcdBytes[position];
|
||||
} else {
|
||||
|
|
|
@ -2017,6 +2017,29 @@ public class NumberFormatterApiTest {
|
|||
assertNotEquals(NumberFormatter.with().locale(ULocale.ENGLISH), NumberFormatter.with().locale(Locale.FRENCH));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formatTypes() {
|
||||
LocalizedNumberFormatter formatter = NumberFormatter.withLocale(ULocale.ENGLISH);
|
||||
|
||||
// Double
|
||||
assertEquals("514.23", formatter.format(514.23).toString());
|
||||
|
||||
// Int64
|
||||
assertEquals("51,423", formatter.format(51423L).toString());
|
||||
|
||||
// BigDecimal
|
||||
assertEquals("987,654,321,234,567,890",
|
||||
formatter.format(new BigDecimal("98765432123456789E1")).toString());
|
||||
|
||||
// Also test proper DecimalQuantity bytes storage when all digits are in the fraction.
|
||||
// The number needs to have exactly 40 digits, which is the size of the default buffer.
|
||||
// (issue discovered by the address sanitizer in C++)
|
||||
assertEquals("0.009876543210987654321098765432109876543211",
|
||||
formatter.rounding(Rounder.unlimited())
|
||||
.format(new BigDecimal("0.009876543210987654321098765432109876543211"))
|
||||
.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void plurals() {
|
||||
// TODO: Expand this test.
|
||||
|
|
Loading…
Add table
Reference in a new issue