Skip to content

Commit

Permalink
ICU-22633 Fix overflow cause by large AM PM value
Browse files Browse the repository at this point in the history
  • Loading branch information
FrankYFTang committed Mar 4, 2024
1 parent 3752624 commit 73744ea
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 1 deletion.
4 changes: 3 additions & 1 deletion icu4c/source/i18n/calendar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3279,7 +3279,9 @@ double Calendar::computeMillisInDay() {
// Don't normalize here; let overflow bump into the next period.
// This is consistent with how we handle other fields.
millisInDay += internalGet(UCAL_HOUR);
millisInDay += 12 * internalGet(UCAL_AM_PM); // Default works for unset AM_PM
// Treat even number as AM and odd nubmber as PM to align with the
// logic in roll()
millisInDay += (internalGet(UCAL_AM_PM) % 2 == 0) ? 0 : 12;
}
}

Expand Down
18 changes: 18 additions & 0 deletions icu4c/source/test/intltest/caltest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ void CalendarTest::runIndexedTest( int32_t index, UBool exec, const char* &name,
TESTCASE_AUTO(Test22633IndianOverflow);
TESTCASE_AUTO(Test22633IslamicUmalquraOverflow);
TESTCASE_AUTO(Test22633PersianOverflow);
TESTCASE_AUTO(Test22633AMPMOverflow);

TESTCASE_AUTO(TestAddOverflow);

Expand Down Expand Up @@ -5677,6 +5678,23 @@ void CalendarTest::Test22633PersianOverflow() {
UCAL_YEAR, status);
assertFalse("Should not return success", U_SUCCESS(status));
}
void CalendarTest::Test22633AMPMOverflow() {
UErrorCode status = U_ZERO_ERROR;
LocalPointer<Calendar> cal(Calendar::createInstance(Locale("en"), status), status);
U_ASSERT(U_SUCCESS(status));
cal->setTimeZone(*TimeZone::getGMT());
cal->clear();
// Test to set a value > limit should not cause internal overflow.
cal->set(UCAL_AM_PM, 370633137);
assertEquals("set large odd value for UCAL_AM_PM should be treated as PM",
12.0 * 60.0 * 60.0 *1000.0, cal->getTime(status));
assertTrue("Should return success", U_SUCCESS(status));

cal->set(UCAL_AM_PM, 370633138);
assertEquals("set large even value for UCAL_AM_PM should be treated as AM",
0.0, cal->getTime(status));
assertTrue("Should return success", U_SUCCESS(status));
}

void CalendarTest::TestChineseCalendarComputeMonthStart() { // ICU-22639
UErrorCode status = U_ZERO_ERROR;
Expand Down
1 change: 1 addition & 0 deletions icu4c/source/test/intltest/caltest.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ class CalendarTest: public CalendarTimeZoneTest {
void Test22633IndianOverflow();
void Test22633IslamicUmalquraOverflow();
void Test22633PersianOverflow();
void Test22633AMPMOverflow();

void verifyFirstDayOfWeek(const char* locale, UCalendarDaysOfWeek expected);
void TestFirstDayOfWeek();
Expand Down

0 comments on commit 73744ea

Please sign in to comment.