@@ -120,6 +120,8 @@ static PyTypeObject PyDateTime_TimeType;
120
120
static PyTypeObject PyDateTime_TZInfoType ;
121
121
static PyTypeObject PyDateTime_TimeZoneType ;
122
122
123
+ static int check_tzinfo_subclass (PyObject * p );
124
+
123
125
_Py_IDENTIFIER (as_integer_ratio );
124
126
_Py_IDENTIFIER (fromutc );
125
127
_Py_IDENTIFIER (isoformat );
@@ -400,8 +402,7 @@ check_date_args(int year, int month, int day)
400
402
{
401
403
402
404
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 );
405
406
return -1 ;
406
407
}
407
408
if (month < 1 || month > 12 ) {
@@ -672,6 +673,10 @@ new_date_ex(int year, int month, int day, PyTypeObject *type)
672
673
{
673
674
PyDateTime_Date * self ;
674
675
676
+ if (check_date_args (year , month , day ) < 0 ) {
677
+ return NULL ;
678
+ }
679
+
675
680
self = (PyDateTime_Date * ) (type -> tp_alloc (type , 0 ));
676
681
if (self != NULL )
677
682
set_date_fields (self , year , month , day );
@@ -689,6 +694,16 @@ new_datetime_ex2(int year, int month, int day, int hour, int minute,
689
694
PyDateTime_DateTime * self ;
690
695
char aware = tzinfo != Py_None ;
691
696
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
+
692
707
self = (PyDateTime_DateTime * ) (type -> tp_alloc (type , aware ));
693
708
if (self != NULL ) {
694
709
self -> hastzinfo = aware ;
@@ -726,6 +741,13 @@ new_time_ex2(int hour, int minute, int second, int usecond,
726
741
PyDateTime_Time * self ;
727
742
char aware = tzinfo != Py_None ;
728
743
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
+
729
751
self = (PyDateTime_Time * ) (type -> tp_alloc (type , aware ));
730
752
if (self != NULL ) {
731
753
self -> hastzinfo = aware ;
@@ -2500,8 +2522,6 @@ date_new(PyTypeObject *type, PyObject *args, PyObject *kw)
2500
2522
2501
2523
if (PyArg_ParseTupleAndKeywords (args , kw , "iii" , date_kws ,
2502
2524
& year , & month , & day )) {
2503
- if (check_date_args (year , month , day ) < 0 )
2504
- return NULL ;
2505
2525
self = new_date_ex (year , month , day , type );
2506
2526
}
2507
2527
return self ;
@@ -3586,10 +3606,6 @@ time_new(PyTypeObject *type, PyObject *args, PyObject *kw)
3586
3606
if (PyArg_ParseTupleAndKeywords (args , kw , "|iiiiO$i" , time_kws ,
3587
3607
& hour , & minute , & second , & usecond ,
3588
3608
& 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 ;
3593
3609
self = new_time_ex2 (hour , minute , second , usecond , tzinfo , fold ,
3594
3610
type );
3595
3611
}
@@ -4176,12 +4192,6 @@ datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw)
4176
4192
if (PyArg_ParseTupleAndKeywords (args , kw , "iii|iiiiO$i" , datetime_kws ,
4177
4193
& year , & month , & day , & hour , & minute ,
4178
4194
& 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 ;
4185
4195
self = new_datetime_ex2 (year , month , day ,
4186
4196
hour , minute , second , usecond ,
4187
4197
tzinfo , fold , type );
@@ -4203,7 +4213,15 @@ static long long
4203
4213
utc_to_seconds (int year , int month , int day ,
4204
4214
int hour , int minute , int second )
4205
4215
{
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 );
4207
4225
return ((ordinal * 24 + hour ) * 60 + minute ) * 60 + second ;
4208
4226
}
4209
4227
@@ -4219,7 +4237,6 @@ local(long long u)
4219
4237
"timestamp out of range for platform time_t" );
4220
4238
return -1 ;
4221
4239
}
4222
- /* XXX: add bounds checking */
4223
4240
if (_PyTime_localtime (t , & local_time ) != 0 )
4224
4241
return -1 ;
4225
4242
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,
4257
4274
*/
4258
4275
second = Py_MIN (59 , tm .tm_sec );
4259
4276
4277
+ /* local timezone requires to compute fold */
4260
4278
if (tzinfo == Py_None && f == _PyTime_localtime ) {
4261
4279
long long probe_seconds , result_seconds , transition ;
4262
4280
@@ -4516,12 +4534,13 @@ add_datetime_timedelta(PyDateTime_DateTime *date, PyDateTime_Delta *delta,
4516
4534
4517
4535
assert (factor == 1 || factor == -1 );
4518
4536
if (normalize_datetime (& year , & month , & day ,
4519
- & hour , & minute , & second , & microsecond ) < 0 )
4537
+ & hour , & minute , & second , & microsecond ) < 0 ) {
4520
4538
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 );
4525
4544
}
4526
4545
4527
4546
static PyObject *
0 commit comments