ICU-13538 in ICU4C Islamic cal, use int64_t math for one operation to avoid overflow; add tests in C and J
X-SVN-Rev: 40882
This commit is contained in:
parent
ba8b599ab5
commit
64aa4beb28
@ -614,7 +614,7 @@ void IslamicCalendar::handleComputeFields(int32_t julianDay, UErrorCode &status)
|
||||
days = julianDay - ASTRONOMICAL_EPOC;
|
||||
}
|
||||
// Use the civil calendar approximation, which is just arithmetic
|
||||
year = (int)ClockMath::floorDivide( (double)(30 * days + 10646) , 10631.0 );
|
||||
year = (int32_t)ClockMath::floorDivide(30 * (int64_t)days + 10646, (int64_t)10631);
|
||||
month = (int32_t)uprv_ceil((days - 29 - yearStart(year)) / 29.5 );
|
||||
month = month<11?month:11;
|
||||
startDate = monthStart(year, month);
|
||||
|
@ -93,6 +93,7 @@ CalendarRegressionTest::runIndexedTest( int32_t index, UBool exec, const char* &
|
||||
CASE(50,TestT9452);
|
||||
CASE(51,TestT11632);
|
||||
CASE(52,TestPersianCalOverflow);
|
||||
CASE(53,TestIslamicCalOverflow);
|
||||
default: name = ""; break;
|
||||
}
|
||||
}
|
||||
@ -3009,9 +3010,9 @@ void CalendarRegressionTest::TestPersianCalOverflow(void) {
|
||||
month = cal->get(UCAL_MONTH, status);
|
||||
dayOfMonth = cal->get(UCAL_DATE, status);
|
||||
if ( U_FAILURE(status) ) {
|
||||
errln("FAIL: Calendar->get MONTH/DATE for localeID %s, julianDay %d, status %s\n", localeID, jd, u_errorName(status));
|
||||
errln("FAIL: Calendar->get MONTH/DATE for localeID %s, julianDay %d, status %s", localeID, jd, u_errorName(status));
|
||||
} else if (month > maxMonth || dayOfMonth > maxDayOfMonth) {
|
||||
errln("FAIL: localeID %s, julianDay %d; maxMonth %d, got month %d; maxDayOfMonth %d, got dayOfMonth %d\n",
|
||||
errln("FAIL: localeID %s, julianDay %d; maxMonth %d, got month %d; maxDayOfMonth %d, got dayOfMonth %d",
|
||||
localeID, jd, maxMonth, month, maxDayOfMonth, dayOfMonth);
|
||||
}
|
||||
}
|
||||
@ -3019,4 +3020,35 @@ void CalendarRegressionTest::TestPersianCalOverflow(void) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @bug tickets 12661, 13538
|
||||
*/
|
||||
void CalendarRegressionTest::TestIslamicCalOverflow(void) {
|
||||
const char* localeID = "ar@calendar=islamic-civil";
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
Calendar* cal = Calendar::createInstance(Locale(localeID), status);
|
||||
if(U_FAILURE(status)) {
|
||||
dataerrln("FAIL: Calendar::createInstance for localeID %s: %s", localeID, u_errorName(status));
|
||||
} else {
|
||||
int32_t maxMonth = cal->getMaximum(UCAL_MONTH);
|
||||
int32_t maxDayOfMonth = cal->getMaximum(UCAL_DATE);
|
||||
int32_t jd, year, month, dayOfMonth;
|
||||
for (jd = 73530872; jd <= 73530876; jd++) { // year 202002, int32_t overflow if jd >= 73530874
|
||||
status = U_ZERO_ERROR;
|
||||
cal->clear();
|
||||
cal->set(UCAL_JULIAN_DAY, jd);
|
||||
year = cal->get(UCAL_YEAR, status);
|
||||
month = cal->get(UCAL_MONTH, status);
|
||||
dayOfMonth = cal->get(UCAL_DATE, status);
|
||||
if ( U_FAILURE(status) ) {
|
||||
errln("FAIL: Calendar->get YEAR/MONTH/DATE for localeID %s, julianDay %d, status %s", localeID, jd, u_errorName(status));
|
||||
} else if (month > maxMonth || dayOfMonth > maxDayOfMonth) {
|
||||
errln("FAIL: localeID %s, julianDay %d; got year %d; maxMonth %d, got month %d; maxDayOfMonth %d, got dayOfMonth %d",
|
||||
localeID, jd, year, maxMonth, month, maxDayOfMonth, dayOfMonth);
|
||||
}
|
||||
}
|
||||
delete cal;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
@ -79,6 +79,7 @@ public:
|
||||
void TestT9452(void);
|
||||
void TestT11632(void);
|
||||
void TestPersianCalOverflow(void);
|
||||
void TestIslamicCalOverflow(void);
|
||||
|
||||
void printdate(GregorianCalendar *cal, const char *string);
|
||||
void dowTest(UBool lenient) ;
|
||||
|
@ -2521,5 +2521,25 @@ public class CalendarRegressionTest extends com.ibm.icu.dev.test.TestFmwk {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestIslamicCalOverflow() {
|
||||
String localeID = "ar@calendar=islamic-civil";
|
||||
Calendar cal = Calendar.getInstance(new ULocale(localeID));
|
||||
int maxMonth = cal.getMaximum(Calendar.MONTH);
|
||||
int maxDayOfMonth = cal.getMaximum(Calendar.DATE);
|
||||
int jd, year, month, dayOfMonth;
|
||||
for (jd = 73530872; jd <= 73530876; jd++) { // year 202002, int32_t overflow if jd >= 73530874
|
||||
cal.clear();
|
||||
cal.set(Calendar.JULIAN_DAY, jd);
|
||||
year = cal.get(Calendar.YEAR);
|
||||
month = cal.get(Calendar.MONTH);
|
||||
dayOfMonth = cal.get(Calendar.DATE);
|
||||
if (month > maxMonth || dayOfMonth > maxDayOfMonth) {
|
||||
errln("Error: localeID " + localeID + ", julianDay " + jd + "; got year " + year + "; maxMonth " + maxMonth +
|
||||
", got month " + month + "; maxDayOfMonth " + maxDayOfMonth + ", got dayOfMonth " + dayOfMonth);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//eof
|
||||
|
Loading…
Reference in New Issue
Block a user