Skip to content

Commit

Permalink
ICU-22513 Return error if days is too large in IslamicUmalquraCalendar
Browse files Browse the repository at this point in the history
The computation in IslamicUmalquraCalendar is slower than others, if the
days is more than 10,000 years from the epoch, we just return error
to avoid hang.
  • Loading branch information
FrankYFTang committed Oct 25, 2023
1 parent 3d1dee6 commit 75afd68
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 0 deletions.
8 changes: 8 additions & 0 deletions icu4c/source/i18n/islamcal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -881,6 +881,8 @@ int32_t IslamicUmalquraCalendar::handleGetYearLength(int32_t extendedYear) const
return len;
}

constexpr int32_t kIslamicUmalquarDaysLimit = 36500000; // About 100000 years.

/**
* Override Calendar to compute several fields specific to the Islamic
* calendar system. These are:
Expand All @@ -902,6 +904,12 @@ void IslamicUmalquraCalendar::handleComputeFields(int32_t julianDay, UErrorCode
int32_t year, month, dayOfMonth, dayOfYear;
int32_t days = julianDay - getEpoc();

// If the days is too large, we just return U_ILLEGAL_ARGUMENT_ERROR
if (days > kIslamicUmalquarDaysLimit) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}

int32_t umalquraStartdays = yearStart(UMALQURA_YEAR_START) ;
if (days < umalquraStartdays) {
//Use Civil calculation
Expand Down
13 changes: 13 additions & 0 deletions icu4c/source/test/intltest/incaltst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ void IntlCalendarTest::runIndexedTest( int32_t index, UBool exec, const char* &n
TESTCASE_AUTO(TestConsistencyIslamicUmalqura);
TESTCASE_AUTO(TestConsistencyPersian);
TESTCASE_AUTO(TestConsistencyJapanese);
TESTCASE_AUTO(TestIslamicUmalquraCalendarSlow);
TESTCASE_AUTO_END;
}

Expand Down Expand Up @@ -1122,6 +1123,18 @@ void IntlCalendarTest::checkConsistency(const char* locale) {
}
}

void IntlCalendarTest::TestIslamicUmalquraCalendarSlow() {
IcuTestErrorCode status(*this, "TestIslamicUmalquraCalendarSlow");
Locale l("th@calendar=islamic-umalqura");
std::unique_ptr<Calendar> cal(
Calendar::createInstance(l, status));
cal->add(UCAL_YEAR, 1229080905, status);
cal->roll(UCAL_WEEK_OF_MONTH, 1499050699, status);
cal->fieldDifference(0.000000, UCAL_YEAR_WOY, status);
// Ignore the error
status.reset();
}

void IntlCalendarTest::simpleTest(const Locale& loc, const UnicodeString& expect, UDate expectDate, UErrorCode& status)
{
UnicodeString tmp;
Expand Down
1 change: 1 addition & 0 deletions icu4c/source/test/intltest/incaltst.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class IntlCalendarTest: public CalendarTimeZoneTest {
void TestConsistencyIslamicUmalqura();
void TestConsistencyPersian();
void TestConsistencyJapanese();
void TestIslamicUmalquraCalendarSlow();

protected:
// Test a Gregorian-Like calendar
Expand Down

0 comments on commit 75afd68

Please sign in to comment.