@@ -120,6 +120,8 @@ static PyTypeObject PyDateTime_TimeType;
120120static PyTypeObject PyDateTime_TZInfoType ;
121121static PyTypeObject PyDateTime_TimeZoneType ;
122122
123+ static int check_tzinfo_subclass (PyObject * p );
124+
123125_Py_IDENTIFIER (as_integer_ratio );
124126_Py_IDENTIFIER (fromutc );
125127_Py_IDENTIFIER (isoformat );
@@ -400,8 +402,7 @@ check_date_args(int year, int month, int day)
400402{
401403
402404 if (year < MINYEAR || year > MAXYEAR ) {
403- PyErr_SetString (PyExc_ValueError ,
404- "year is out of range" );
405+ PyErr_Format (PyExc_ValueError , "year %i is out of range" , year );
405406 return -1 ;
406407 }
407408 if (month < 1 || month > 12 ) {
@@ -672,6 +673,10 @@ new_date_ex(int year, int month, int day, PyTypeObject *type)
672673{
673674 PyDateTime_Date * self ;
674675
676+ if (check_date_args (year , month , day ) < 0 ) {
677+ return NULL ;
678+ }
679+
675680 self = (PyDateTime_Date * ) (type -> tp_alloc (type , 0 ));
676681 if (self != NULL )
677682 set_date_fields (self , year , month , day );
@@ -689,6 +694,16 @@ new_datetime_ex2(int year, int month, int day, int hour, int minute,
689694 PyDateTime_DateTime * self ;
690695 char aware = tzinfo != Py_None ;
691696
697+ if (check_date_args (year , month , day ) < 0 ) {
698+ return NULL ;
699+ }
700+ if (check_time_args (hour , minute , second , usecond , fold ) < 0 ) {
701+ return NULL ;
702+ }
703+ if (check_tzinfo_subclass (tzinfo ) < 0 ) {
704+ return NULL ;
705+ }
706+
692707 self = (PyDateTime_DateTime * ) (type -> tp_alloc (type , aware ));
693708 if (self != NULL ) {
694709 self -> hastzinfo = aware ;
@@ -726,6 +741,13 @@ new_time_ex2(int hour, int minute, int second, int usecond,
726741 PyDateTime_Time * self ;
727742 char aware = tzinfo != Py_None ;
728743
744+ if (check_time_args (hour , minute , second , usecond , fold ) < 0 ) {
745+ return NULL ;
746+ }
747+ if (check_tzinfo_subclass (tzinfo ) < 0 ) {
748+ return NULL ;
749+ }
750+
729751 self = (PyDateTime_Time * ) (type -> tp_alloc (type , aware ));
730752 if (self != NULL ) {
731753 self -> hastzinfo = aware ;
@@ -2500,8 +2522,6 @@ date_new(PyTypeObject *type, PyObject *args, PyObject *kw)
25002522
25012523 if (PyArg_ParseTupleAndKeywords (args , kw , "iii" , date_kws ,
25022524 & year , & month , & day )) {
2503- if (check_date_args (year , month , day ) < 0 )
2504- return NULL ;
25052525 self = new_date_ex (year , month , day , type );
25062526 }
25072527 return self ;
@@ -3586,10 +3606,6 @@ time_new(PyTypeObject *type, PyObject *args, PyObject *kw)
35863606 if (PyArg_ParseTupleAndKeywords (args , kw , "|iiiiO$i" , time_kws ,
35873607 & hour , & minute , & second , & usecond ,
35883608 & tzinfo , & fold )) {
3589- if (check_time_args (hour , minute , second , usecond , fold ) < 0 )
3590- return NULL ;
3591- if (check_tzinfo_subclass (tzinfo ) < 0 )
3592- return NULL ;
35933609 self = new_time_ex2 (hour , minute , second , usecond , tzinfo , fold ,
35943610 type );
35953611 }
@@ -4176,12 +4192,6 @@ datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw)
41764192 if (PyArg_ParseTupleAndKeywords (args , kw , "iii|iiiiO$i" , datetime_kws ,
41774193 & year , & month , & day , & hour , & minute ,
41784194 & second , & usecond , & tzinfo , & fold )) {
4179- if (check_date_args (year , month , day ) < 0 )
4180- return NULL ;
4181- if (check_time_args (hour , minute , second , usecond , fold ) < 0 )
4182- return NULL ;
4183- if (check_tzinfo_subclass (tzinfo ) < 0 )
4184- return NULL ;
41854195 self = new_datetime_ex2 (year , month , day ,
41864196 hour , minute , second , usecond ,
41874197 tzinfo , fold , type );
@@ -4203,7 +4213,15 @@ static long long
42034213utc_to_seconds (int year , int month , int day ,
42044214 int hour , int minute , int second )
42054215{
4206- long long ordinal = ymd_to_ord (year , month , day );
4216+ long long ordinal ;
4217+
4218+ /* ymd_to_ord() doesn't support year <= 0 */
4219+ if (year < MINYEAR || year > MAXYEAR ) {
4220+ PyErr_Format (PyExc_ValueError , "year %i is out of range" , year );
4221+ return -1 ;
4222+ }
4223+
4224+ ordinal = ymd_to_ord (year , month , day );
42074225 return ((ordinal * 24 + hour ) * 60 + minute ) * 60 + second ;
42084226}
42094227
@@ -4219,7 +4237,6 @@ local(long long u)
42194237 "timestamp out of range for platform time_t" );
42204238 return -1 ;
42214239 }
4222- /* XXX: add bounds checking */
42234240 if (_PyTime_localtime (t , & local_time ) != 0 )
42244241 return -1 ;
42254242 return utc_to_seconds (local_time .tm_year + 1900 ,
@@ -4257,6 +4274,7 @@ datetime_from_timet_and_us(PyObject *cls, TM_FUNC f, time_t timet, int us,
42574274 */
42584275 second = Py_MIN (59 , tm .tm_sec );
42594276
4277+ /* local timezone requires to compute fold */
42604278 if (tzinfo == Py_None && f == _PyTime_localtime ) {
42614279 long long probe_seconds , result_seconds , transition ;
42624280
@@ -4516,12 +4534,13 @@ add_datetime_timedelta(PyDateTime_DateTime *date, PyDateTime_Delta *delta,
45164534
45174535 assert (factor == 1 || factor == -1 );
45184536 if (normalize_datetime (& year , & month , & day ,
4519- & hour , & minute , & second , & microsecond ) < 0 )
4537+ & hour , & minute , & second , & microsecond ) < 0 ) {
45204538 return NULL ;
4521- else
4522- return new_datetime (year , month , day ,
4523- hour , minute , second , microsecond ,
4524- HASTZINFO (date ) ? date -> tzinfo : Py_None , 0 );
4539+ }
4540+
4541+ return new_datetime (year , month , day ,
4542+ hour , minute , second , microsecond ,
4543+ HASTZINFO (date ) ? date -> tzinfo : Py_None , 0 );
45254544}
45264545
45274546static PyObject *
0 commit comments