From 4c9ef1a31bc41cd4af5880bb04761c9893c770dc Mon Sep 17 00:00:00 2001 From: Frank Tang Date: Thu, 19 Dec 2024 16:26:45 -0800 Subject: [PATCH] ICU-22962 Fix int overflow in Calendar::handleComputeJulianDay --- icu4c/source/i18n/calendar.cpp | 7 ++++++- icu4c/source/test/intltest/caltest.cpp | 14 ++++++++++++++ icu4c/source/test/intltest/caltest.h | 1 + 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/icu4c/source/i18n/calendar.cpp b/icu4c/source/i18n/calendar.cpp index c3643a986896..1dcf08a2eaf7 100644 --- a/icu4c/source/i18n/calendar.cpp +++ b/icu4c/source/i18n/calendar.cpp @@ -3607,7 +3607,12 @@ int32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField, UErrorCo fprintf(stderr, "%s:%d - y=%d, y-1=%d doy%d, njd%d (C.F. %d)\n", __FILE__, __LINE__, year, year-1, testDate, julianDay+testDate, nextJulianDay); #endif - if(julianDay+testDate > nextJulianDay) { // is it past Dec 31? (nextJulianDay is day BEFORE year+1's Jan 1) + if (uprv_add32_overflow(julianDay, testDate, &testDate)) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + + if(testDate > nextJulianDay) { // is it past Dec 31? (nextJulianDay is day BEFORE year+1's Jan 1) // Fire up the calculating engines.. retry YWOY = (year-1) int32_t prevYear; if (uprv_add32_overflow(year, -1, &prevYear)) { diff --git a/icu4c/source/test/intltest/caltest.cpp b/icu4c/source/test/intltest/caltest.cpp index 83b410967c4b..121170857798 100644 --- a/icu4c/source/test/intltest/caltest.cpp +++ b/icu4c/source/test/intltest/caltest.cpp @@ -193,6 +193,7 @@ void CalendarTest::runIndexedTest( int32_t index, UBool exec, const char* &name, TESTCASE_AUTO(Test22633ChineseOverflow); TESTCASE_AUTO(Test22962ChineseOverflow); + TESTCASE_AUTO(Test22962BuddhistOverflow); TESTCASE_AUTO(Test22633IndianOverflow); TESTCASE_AUTO(Test22633IslamicUmalquraOverflow); TESTCASE_AUTO(Test22633PersianOverflow); @@ -5665,6 +5666,19 @@ void CalendarTest::Test22633ChineseOverflow() { assertTrue("Should return falure", U_FAILURE(status)); } +void CalendarTest::Test22962BuddhistOverflow() { + UErrorCode status = U_ZERO_ERROR; + LocalPointer cal(Calendar::createInstance(Locale("en@calendar=uddhist"), status), status); + U_ASSERT(U_SUCCESS(status)); + cal->clear(); + cal->set(UCAL_WEEK_OF_YEAR, 1666136); + cal->set(UCAL_YEAR, -1887379272); + cal->fieldDifference( + 261830011167902373443927125260580558779842815957727840993886210772873194951140935848493861585917165011373697198856398176256.000000, + UCAL_YEAR_WOY, status); + assertTrue("Should return falure", U_FAILURE(status)); +} + void CalendarTest::Test22962ChineseOverflow() { UErrorCode status = U_ZERO_ERROR; LocalPointer cal(Calendar::createInstance(Locale("en@calendar=chinese"), status), status); diff --git a/icu4c/source/test/intltest/caltest.h b/icu4c/source/test/intltest/caltest.h index c83c0ffe0440..068db75b56f2 100644 --- a/icu4c/source/test/intltest/caltest.h +++ b/icu4c/source/test/intltest/caltest.h @@ -336,6 +336,7 @@ class CalendarTest: public CalendarTimeZoneTest { void TestRollWeekOfYear(); void Test22633ChineseOverflow(); void Test22962ChineseOverflow(); + void Test22962BuddhistOverflow(); void Test22633IndianOverflow(); void Test22633IslamicUmalquraOverflow(); void Test22633PersianOverflow();