mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-10 07:39:16 +00:00
parent
ae9cc8cbd1
commit
9515e82741
4 changed files with 70 additions and 4 deletions
|
@ -2129,9 +2129,19 @@ void Calendar::add(UCalendarDateFields field, int32_t amount, UErrorCode& status
|
|||
|
||||
switch (field) {
|
||||
case UCAL_ERA:
|
||||
set(field, get(field, status) + amount);
|
||||
{
|
||||
int32_t era = get(UCAL_ERA, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
if (uprv_add32_overflow(era, amount, &era)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return;
|
||||
}
|
||||
set(UCAL_ERA, era);
|
||||
pinField(UCAL_ERA, status);
|
||||
return;
|
||||
}
|
||||
|
||||
case UCAL_YEAR:
|
||||
case UCAL_YEAR_WOY:
|
||||
|
@ -2147,7 +2157,10 @@ void Calendar::add(UCalendarDateFields field, int32_t amount, UErrorCode& status
|
|||
if (era == 0) {
|
||||
const char * calType = getType();
|
||||
if ( uprv_strcmp(calType,"gregorian")==0 || uprv_strcmp(calType,"roc")==0 || uprv_strcmp(calType,"coptic")==0 ) {
|
||||
amount = -amount;
|
||||
if (uprv_mul32_overflow(amount, -1, &amount)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2159,7 +2172,16 @@ void Calendar::add(UCalendarDateFields field, int32_t amount, UErrorCode& status
|
|||
{
|
||||
UBool oldLenient = isLenient();
|
||||
setLenient(true);
|
||||
set(field, get(field, status) + amount);
|
||||
int32_t value = get(field, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
if (uprv_add32_overflow(value, amount, &value)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return;
|
||||
}
|
||||
set(field, value);
|
||||
|
||||
pinField(UCAL_DAY_OF_MONTH, status);
|
||||
if(oldLenient==false) {
|
||||
complete(status); /* force recalculate */
|
||||
|
|
|
@ -34,7 +34,7 @@ int64_t ClockMath::floorDivide(int64_t numerator, int64_t denominator) {
|
|||
|
||||
int32_t ClockMath::floorDivide(int32_t numerator, int32_t denominator,
|
||||
int32_t* remainder) {
|
||||
auto quotient = floorDivide(numerator, denominator);
|
||||
int64_t quotient = floorDivide(numerator, denominator);
|
||||
if (remainder != nullptr) {
|
||||
*remainder = numerator - (quotient * denominator);
|
||||
}
|
||||
|
|
|
@ -190,6 +190,7 @@ void CalendarTest::runIndexedTest( int32_t index, UBool exec, const char* &name,
|
|||
TESTCASE_AUTO(TestDangiOverflowIsLeapMonthBetween22507);
|
||||
TESTCASE_AUTO(TestRollWeekOfYear);
|
||||
TESTCASE_AUTO(TestFirstDayOfWeek);
|
||||
TESTCASE_AUTO(TestAddOverflow);
|
||||
|
||||
TESTCASE_AUTO(TestChineseCalendarComputeMonthStart);
|
||||
|
||||
|
@ -5659,6 +5660,48 @@ void CalendarTest::TestChineseCalendarComputeMonthStart() { // ICU-22639
|
|||
chinese.hasLeapMonthBetweenWinterSolstices);
|
||||
}
|
||||
|
||||
void CalendarTest::TestAddOverflow() {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
LocalPointer<Calendar> calendar(
|
||||
Calendar::createInstance(Locale("en"), status),
|
||||
status);
|
||||
if (failure(status, "Calendar::createInstance")) return;
|
||||
for (int32_t i = 0; i < UCAL_FIELD_COUNT; i++) {
|
||||
status = U_ZERO_ERROR;
|
||||
calendar->setTime(0, status);
|
||||
calendar->add(static_cast<UCalendarDateFields>(i), INT32_MAX / 2, status);
|
||||
calendar->add(static_cast<UCalendarDateFields>(i), INT32_MAX, status);
|
||||
if ((i == UCAL_ERA) ||
|
||||
(i == UCAL_YEAR) ||
|
||||
(i == UCAL_YEAR_WOY) ||
|
||||
(i == UCAL_EXTENDED_YEAR) ||
|
||||
(i == UCAL_IS_LEAP_MONTH) ||
|
||||
(i == UCAL_MONTH) ||
|
||||
(i == UCAL_ORDINAL_MONTH) ||
|
||||
(i == UCAL_ZONE_OFFSET) ||
|
||||
(i == UCAL_DST_OFFSET)) {
|
||||
assertTrue("add INT32_MAX should fail", U_FAILURE(status));
|
||||
} else {
|
||||
assertTrue("add INT32_MAX should still success", U_SUCCESS(status));
|
||||
}
|
||||
|
||||
status = U_ZERO_ERROR;
|
||||
calendar->setTime(0, status);
|
||||
calendar->add(static_cast<UCalendarDateFields>(i), INT32_MIN / 2, status);
|
||||
calendar->add(static_cast<UCalendarDateFields>(i), INT32_MIN, status);
|
||||
if ((i == UCAL_YEAR) ||
|
||||
(i == UCAL_YEAR_WOY) ||
|
||||
(i == UCAL_EXTENDED_YEAR) ||
|
||||
(i == UCAL_IS_LEAP_MONTH) ||
|
||||
(i == UCAL_ZONE_OFFSET) ||
|
||||
(i == UCAL_DST_OFFSET)) {
|
||||
assertTrue("add INT32_MIN should fail", U_FAILURE(status));
|
||||
} else {
|
||||
assertTrue("add INT32_MIN should still success", U_SUCCESS(status));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
||||
//eof
|
||||
|
|
|
@ -332,6 +332,7 @@ public: // package
|
|||
void TestDangiOverflowIsLeapMonthBetween22507();
|
||||
|
||||
void TestFWWithISO8601();
|
||||
void TestAddOverflow();
|
||||
void TestRollWeekOfYear();
|
||||
|
||||
void verifyFirstDayOfWeek(const char* locale, UCalendarDaysOfWeek expected);
|
||||
|
|
Loading…
Add table
Reference in a new issue