]> granicus.if.org Git - python/commitdiff
Closes #27710: Disallow fold not in [0, 1] in time and datetime constructors.
authorAlexander Belopolsky <alexander.belopolsky@gmail.com>
Mon, 8 Aug 2016 21:05:40 +0000 (17:05 -0400)
committerAlexander Belopolsky <alexander.belopolsky@gmail.com>
Mon, 8 Aug 2016 21:05:40 +0000 (17:05 -0400)
Lib/datetime.py
Lib/test/datetimetester.py
Modules/_datetimemodule.c

index 9f942a207e888f18c968d2c905f895b6371c0bab..36374aa94c871a7b658c3a2bcc42060d8a6e6e2d 100644 (file)
@@ -288,7 +288,7 @@ def _check_date_fields(year, month, day):
         raise ValueError('day must be in 1..%d' % dim, day)
     return year, month, day
 
-def _check_time_fields(hour, minute, second, microsecond):
+def _check_time_fields(hour, minute, second, microsecond, fold):
     hour = _check_int_field(hour)
     minute = _check_int_field(minute)
     second = _check_int_field(second)
@@ -301,7 +301,9 @@ def _check_time_fields(hour, minute, second, microsecond):
         raise ValueError('second must be in 0..59', second)
     if not 0 <= microsecond <= 999999:
         raise ValueError('microsecond must be in 0..999999', microsecond)
-    return hour, minute, second, microsecond
+    if fold not in (0, 1):
+        raise ValueError('fold must be either 0 or 1', fold)
+    return hour, minute, second, microsecond, fold
 
 def _check_tzinfo_arg(tz):
     if tz is not None and not isinstance(tz, tzinfo):
@@ -1059,8 +1061,8 @@ class time:
             self.__setstate(hour, minute or None)
             self._hashcode = -1
             return self
-        hour, minute, second, microsecond = _check_time_fields(
-            hour, minute, second, microsecond)
+        hour, minute, second, microsecond, fold = _check_time_fields(
+            hour, minute, second, microsecond, fold)
         _check_tzinfo_arg(tzinfo)
         self = object.__new__(cls)
         self._hour = hour
@@ -1369,8 +1371,8 @@ class datetime(date):
             self._hashcode = -1
             return self
         year, month, day = _check_date_fields(year, month, day)
-        hour, minute, second, microsecond = _check_time_fields(
-            hour, minute, second, microsecond)
+        hour, minute, second, microsecond, fold = _check_time_fields(
+            hour, minute, second, microsecond, fold)
         _check_tzinfo_arg(tzinfo)
         self = object.__new__(cls)
         self._year = year
index e71f3aa9b46500733a4155baab40464e40013cba..726b7fde10acee7b32d507cf84c315e42a2e6500 100644 (file)
@@ -1724,6 +1724,11 @@ class TestDateTime(TestDate):
         self.assertRaises(ValueError, self.theclass,
                           2000, 1, 31, 23, 59, 59,
                           1000000)
+        # bad fold
+        self.assertRaises(ValueError, self.theclass,
+                          2000, 1, 31, fold=-1)
+        self.assertRaises(ValueError, self.theclass,
+                          2000, 1, 31, fold=2)
         # Positional fold:
         self.assertRaises(TypeError, self.theclass,
                           2000, 1, 31, 23, 59, 59, 0, None, 1)
index 3048762034eb25517f09ab112a32b625a2d3783e..a62f5929578d7ea4853545e4d5643b0a8d175875 100644 (file)
@@ -427,7 +427,7 @@ check_date_args(int year, int month, int day)
  * aren't, raise ValueError and return -1.
  */
 static int
-check_time_args(int h, int m, int s, int us)
+check_time_args(int h, int m, int s, int us, int fold)
 {
     if (h < 0 || h > 23) {
         PyErr_SetString(PyExc_ValueError,
@@ -449,6 +449,11 @@ check_time_args(int h, int m, int s, int us)
                         "microsecond must be in 0..999999");
         return -1;
     }
+    if (fold != 0 && fold != 1) {
+        PyErr_SetString(PyExc_ValueError,
+                        "fold must be either 0 or 1");
+        return -1;
+    }
     return 0;
 }
 
@@ -3598,7 +3603,7 @@ time_new(PyTypeObject *type, PyObject *args, PyObject *kw)
     if (PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO$i", time_kws,
                                     &hour, &minute, &second, &usecond,
                                     &tzinfo, &fold)) {
-        if (check_time_args(hour, minute, second, usecond) < 0)
+        if (check_time_args(hour, minute, second, usecond, fold) < 0)
             return NULL;
         if (check_tzinfo_subclass(tzinfo) < 0)
             return NULL;
@@ -3926,8 +3931,14 @@ time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw)
     if (tuple == NULL)
         return NULL;
     clone = time_new(Py_TYPE(self), tuple, NULL);
-    if (clone != NULL)
+    if (clone != NULL) {
+        if (fold != 0 && fold != 1) {
+            PyErr_SetString(PyExc_ValueError,
+                            "fold must be either 0 or 1");
+            return NULL;
+        }
         TIME_SET_FOLD(clone, fold);
+    }
     Py_DECREF(tuple);
     return clone;
 }
@@ -4175,7 +4186,7 @@ datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw)
                                     &second, &usecond, &tzinfo, &fold)) {
         if (check_date_args(year, month, day) < 0)
             return NULL;
-        if (check_time_args(hour, minute, second, usecond) < 0)
+        if (check_time_args(hour, minute, second, usecond, fold) < 0)
             return NULL;
         if (check_tzinfo_subclass(tzinfo) < 0)
             return NULL;
@@ -5006,8 +5017,15 @@ datetime_replace(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
     if (tuple == NULL)
         return NULL;
     clone = datetime_new(Py_TYPE(self), tuple, NULL);
-    if (clone != NULL)
+
+    if (clone != NULL) {
+        if (fold != 0 && fold != 1) {
+            PyErr_SetString(PyExc_ValueError,
+                            "fold must be either 0 or 1");
+            return NULL;
+        }
         DATE_SET_FOLD(clone, fold);
+    }
     Py_DECREF(tuple);
     return clone;
 }