@@ -60,13 +60,18 @@ static icu::CalendarCache *gNewYearCache = nullptr;
60
60
static icu::TimeZone *gAstronomerTimeZone = nullptr ;
61
61
static icu::UInitOnce gAstronomerTimeZoneInitOnce {};
62
62
63
+ /*
64
+ * The start year of the Chinese calendar, 1CE.
65
+ */
66
+ static const int32_t CHINESE_EPOCH_YEAR = 1 ; // Gregorian year
67
+ //
63
68
/* *
64
- * The start year of the Chinese calendar, the 61st year of the reign
65
- * of Huang Di. Some sources use the first year of his reign,
66
- * resulting in EXTENDED_YEAR values 60 years greater and ERA (cycle)
67
- * values one greater.
69
+ * The start year of the Chinese calendar for cycle calculation,
70
+ * the 61st year of the reign of Huang Di.
71
+ * Some sources use the first year of his reign,
72
+ * resulting in ERA (cycle) values one greater.
68
73
*/
69
- static const int32_t CHINESE_EPOCH_YEAR = -2636 ; // Gregorian year
74
+ static const int32_t CYCLE_EPOCH = -2636 ; // Gregorian year
70
75
71
76
/* *
72
77
* The offset from GMT in milliseconds at which we perform astronomical
@@ -226,16 +231,12 @@ int32_t ChineseCalendar::handleGetExtendedYear(UErrorCode& status) {
226
231
// adjust to the instance specific epoch
227
232
int32_t cycle = internalGet (UCAL_ERA, 1 );
228
233
year = internalGet (UCAL_YEAR, 1 );
229
- const Setting setting = getSetting (status);
230
- if (U_FAILURE (status)) {
231
- return 0 ;
232
- }
233
234
// Handle int32 overflow calculation for
234
- // year = year + (cycle-1) * 60 -(fEpochYear - CHINESE_EPOCH_YEAR)
235
+ // year = year + (cycle-1) * 60 + CYCLE_EPOCH - CHINESE_EPOCH_YEAR
235
236
if (uprv_add32_overflow (cycle, -1 , &cycle) || // 0-based cycle
236
237
uprv_mul32_overflow (cycle, 60 , &cycle) ||
237
238
uprv_add32_overflow (year, cycle, &year) ||
238
- uprv_add32_overflow (year, -(setting. epochYear - CHINESE_EPOCH_YEAR) ,
239
+ uprv_add32_overflow (year, CYCLE_EPOCH- CHINESE_EPOCH_YEAR,
239
240
&year)) {
240
241
status = U_ILLEGAL_ARGUMENT_ERROR;
241
242
return 0 ;
@@ -362,12 +363,7 @@ int64_t ChineseCalendar::handleComputeMonthStartWithLeap(int32_t eyear, int32_t
362
363
if (U_FAILURE (status)) {
363
364
return 0 ;
364
365
}
365
- int32_t gyear;
366
- if (uprv_add32_overflow (eyear, setting.epochYear - 1 , &gyear)) {
367
- status = U_ILLEGAL_ARGUMENT_ERROR;
368
- return 0 ;
369
- }
370
-
366
+ int32_t gyear = eyear;
371
367
int32_t theNewYear = newYear (setting, gyear, status);
372
368
int32_t newMoon = newMoonNear (setting.zoneAstroCalc , theNewYear + month * 29 , true , status);
373
369
if (U_FAILURE (status)) {
@@ -791,10 +787,20 @@ struct MonthInfo computeMonthInfo(
791
787
return output;
792
788
}
793
789
if (days < solsticeAfter) {
794
- solsticeBefore = winterSolstice (setting, gyear - 1 , status);
790
+ int32_t gprevious_year;
791
+ if (uprv_add32_overflow (gyear, -1 , &gprevious_year)) {
792
+ status = U_ILLEGAL_ARGUMENT_ERROR;
793
+ return output;
794
+ }
795
+ solsticeBefore = winterSolstice (setting, gprevious_year, status);
795
796
} else {
796
797
solsticeBefore = solsticeAfter;
797
- solsticeAfter = winterSolstice (setting, gyear + 1 , status);
798
+ int32_t gnext_year;
799
+ if (uprv_add32_overflow (gyear, 1 , &gnext_year)) {
800
+ status = U_ILLEGAL_ARGUMENT_ERROR;
801
+ return output;
802
+ }
803
+ solsticeAfter = winterSolstice (setting, gnext_year, status);
798
804
}
799
805
if (!(solsticeBefore <= days && days < solsticeAfter)) {
800
806
status = U_ILLEGAL_ARGUMENT_ERROR;
@@ -824,7 +830,12 @@ struct MonthInfo computeMonthInfo(
824
830
return output;
825
831
}
826
832
if (days < theNewYear) {
827
- theNewYear = newYear (setting, gyear-1 , status);
833
+ int32_t gprevious_year;
834
+ if (uprv_add32_overflow (gyear, -1 , &gprevious_year)) {
835
+ status = U_ILLEGAL_ARGUMENT_ERROR;
836
+ return output;
837
+ }
838
+ theNewYear = newYear (setting, gprevious_year, status);
828
839
if (U_FAILURE (status)) {
829
840
return output;
830
841
}
@@ -897,12 +908,21 @@ void ChineseCalendar::handleComputeFields(int32_t julianDay, UErrorCode & status
897
908
hasLeapMonthBetweenWinterSolstices = monthInfo.hasLeapMonthBetweenWinterSolstices ;
898
909
899
910
// Extended year and cycle year is based on the epoch year
900
- int32_t eyear = gyear - setting.epochYear ;
901
- int32_t cycle_year = gyear - CHINESE_EPOCH_YEAR;
911
+ int32_t eyear;
912
+ int32_t cycle_year;
913
+ if (uprv_add32_overflow (gyear, -CHINESE_EPOCH_YEAR, &eyear) ||
914
+ uprv_add32_overflow (gyear, -CYCLE_EPOCH, &cycle_year)) {
915
+ status = U_ILLEGAL_ARGUMENT_ERROR;
916
+ return ;
917
+ }
902
918
if (monthInfo.month < 11 ||
903
919
gmonth >= UCAL_JULY) {
904
- eyear++;
905
- cycle_year++;
920
+ // forward to next year
921
+ if (uprv_add32_overflow (eyear, 1 , &eyear) ||
922
+ uprv_add32_overflow (cycle_year, 1 , &cycle_year)) {
923
+ status = U_ILLEGAL_ARGUMENT_ERROR;
924
+ return ;
925
+ }
906
926
}
907
927
int32_t dayOfMonth = days - monthInfo.thisMoon + 1 ;
908
928
@@ -919,7 +939,12 @@ void ChineseCalendar::handleComputeFields(int32_t julianDay, UErrorCode & status
919
939
return ;
920
940
}
921
941
if (days < theNewYear) {
922
- theNewYear = newYear (setting, gyear-1 , status);
942
+ int32_t gprevious_year;
943
+ if (uprv_add32_overflow (gyear, -1 , &gprevious_year)) {
944
+ status = U_ILLEGAL_ARGUMENT_ERROR;
945
+ return ;
946
+ }
947
+ theNewYear = newYear (setting, gprevious_year, status);
923
948
}
924
949
if (U_FAILURE (status)) {
925
950
return ;
@@ -982,7 +1007,12 @@ int32_t newYear(const icu::ChineseCalendar::Setting& setting,
982
1007
983
1008
if (cacheValue == 0 ) {
984
1009
985
- int32_t solsticeBefore= winterSolstice (setting, gyear - 1 , status);
1010
+ int32_t gprevious_year;
1011
+ if (uprv_add32_overflow (gyear, -1 , &gprevious_year)) {
1012
+ status = U_ILLEGAL_ARGUMENT_ERROR;
1013
+ return 0 ;
1014
+ }
1015
+ int32_t solsticeBefore= winterSolstice (setting, gprevious_year, status);
986
1016
int32_t solsticeAfter = winterSolstice (setting, gyear, status);
987
1017
int32_t newMoon1 = newMoonNear (timeZone, solsticeBefore + 1 , true , status);
988
1018
int32_t newMoon2 = newMoonNear (timeZone, newMoon1 + SYNODIC_GAP, true , status);
@@ -1074,10 +1104,6 @@ void ChineseCalendar::offsetMonth(int32_t newMoon, int32_t dayOfMonth, int32_t d
1074
1104
}
1075
1105
}
1076
1106
1077
- int32_t ChineseCalendar::getRelatedYearDifference () const {
1078
- return CHINESE_EPOCH_YEAR - 1 ;
1079
- }
1080
-
1081
1107
IMPL_SYSTEM_DEFAULT_CENTURY (ChineseCalendar, " @calendar=chinese" )
1082
1108
1083
1109
bool
@@ -1172,7 +1198,6 @@ int32_t ChineseCalendar::internalGetMonth(int32_t defaultValue, UErrorCode& stat
1172
1198
1173
1199
ChineseCalendar::Setting ChineseCalendar::getSetting (UErrorCode&) const {
1174
1200
return {
1175
- CHINESE_EPOCH_YEAR,
1176
1201
getAstronomerTimeZone (),
1177
1202
&gWinterSolsticeCache ,
1178
1203
&gNewYearCache
0 commit comments