summaryrefslogtreecommitdiff
path: root/Modules/_datetimemodule.c
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2018-11-20 20:41:09 +0200
committerGitHub <noreply@github.com>2018-11-20 20:41:09 +0200
commit3ec0f495163da3b7a15deb2805cec48aed432f58 (patch)
tree8a8cf87e228bfa33fa0781dd64f3ace0d0cb655d /Modules/_datetimemodule.c
parent97f1efb6062188645a470daaa91e3669d739c75f (diff)
downloadcpython-git-3ec0f495163da3b7a15deb2805cec48aed432f58.tar.gz
bpo-35021: Fix assertion failures in _datetimemodule.c. (GH-10039)
Fixes assertion failures in _datetimemodule.c introduced in the previous fix (see bpo-31752). Rather of trying to handle an int subclass as exact int, let it to use overridden special methods, but check the result of divmod().
Diffstat (limited to 'Modules/_datetimemodule.c')
-rw-r--r--Modules/_datetimemodule.c99
1 files changed, 51 insertions, 48 deletions
diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c
index 02c510f055..371bfaec3a 100644
--- a/Modules/_datetimemodule.c
+++ b/Modules/_datetimemodule.c
@@ -1797,6 +1797,29 @@ Done:
return result;
}
+static PyObject *
+checked_divmod(PyObject *a, PyObject *b)
+{
+ PyObject *result = PyNumber_Divmod(a, b);
+ if (result != NULL) {
+ if (!PyTuple_Check(result)) {
+ PyErr_Format(PyExc_TypeError,
+ "divmod() returned non-tuple (type %.200s)",
+ result->ob_type->tp_name);
+ Py_DECREF(result);
+ return NULL;
+ }
+ if (PyTuple_GET_SIZE(result) != 2) {
+ PyErr_Format(PyExc_TypeError,
+ "divmod() returned a tuple of size %zd",
+ PyTuple_GET_SIZE(result));
+ Py_DECREF(result);
+ return NULL;
+ }
+ }
+ return result;
+}
+
/* Convert a number of us (as a Python int) to a timedelta.
*/
static PyObject *
@@ -1805,70 +1828,49 @@ microseconds_to_delta_ex(PyObject *pyus, PyTypeObject *type)
int us;
int s;
int d;
- long temp;
PyObject *tuple = NULL;
PyObject *num = NULL;
PyObject *result = NULL;
- assert(PyLong_CheckExact(pyus));
- tuple = PyNumber_Divmod(pyus, us_per_second);
- if (tuple == NULL)
+ tuple = checked_divmod(pyus, us_per_second);
+ if (tuple == NULL) {
goto Done;
+ }
- num = PyTuple_GetItem(tuple, 1); /* us */
- if (num == NULL)
- goto Done;
- temp = PyLong_AsLong(num);
+ num = PyTuple_GET_ITEM(tuple, 1); /* us */
+ us = _PyLong_AsInt(num);
num = NULL;
- if (temp == -1 && PyErr_Occurred())
- goto Done;
- assert(0 <= temp && temp < 1000000);
- us = (int)temp;
- if (us < 0) {
- /* The divisor was positive, so this must be an error. */
- assert(PyErr_Occurred());
+ if (us == -1 && PyErr_Occurred()) {
goto Done;
}
+ if (!(0 <= us && us < 1000000)) {
+ goto BadDivmod;
+ }
- num = PyTuple_GetItem(tuple, 0); /* leftover seconds */
- if (num == NULL)
- goto Done;
+ num = PyTuple_GET_ITEM(tuple, 0); /* leftover seconds */
Py_INCREF(num);
Py_DECREF(tuple);
- tuple = PyNumber_Divmod(num, seconds_per_day);
+ tuple = checked_divmod(num, seconds_per_day);
if (tuple == NULL)
goto Done;
Py_DECREF(num);
- num = PyTuple_GetItem(tuple, 1); /* seconds */
- if (num == NULL)
- goto Done;
- temp = PyLong_AsLong(num);
+ num = PyTuple_GET_ITEM(tuple, 1); /* seconds */
+ s = _PyLong_AsInt(num);
num = NULL;
- if (temp == -1 && PyErr_Occurred())
- goto Done;
- assert(0 <= temp && temp < 24*3600);
- s = (int)temp;
-
- if (s < 0) {
- /* The divisor was positive, so this must be an error. */
- assert(PyErr_Occurred());
+ if (s == -1 && PyErr_Occurred()) {
goto Done;
}
+ if (!(0 <= s && s < 24*3600)) {
+ goto BadDivmod;
+ }
- num = PyTuple_GetItem(tuple, 0); /* leftover days */
- if (num == NULL)
- goto Done;
+ num = PyTuple_GET_ITEM(tuple, 0); /* leftover days */
Py_INCREF(num);
- temp = PyLong_AsLong(num);
- if (temp == -1 && PyErr_Occurred())
- goto Done;
- d = (int)temp;
- if ((long)d != temp) {
- PyErr_SetString(PyExc_OverflowError, "normalized days too "
- "large to fit in a C int");
+ d = _PyLong_AsInt(num);
+ if (d == -1 && PyErr_Occurred()) {
goto Done;
}
result = new_delta_ex(d, s, us, 0, type);
@@ -1877,6 +1879,11 @@ Done:
Py_XDECREF(tuple);
Py_XDECREF(num);
return result;
+
+BadDivmod:
+ PyErr_SetString(PyExc_TypeError,
+ "divmod() returned a value out of range");
+ goto Done;
}
#define microseconds_to_delta(pymicros) \
@@ -1893,7 +1900,7 @@ multiply_int_timedelta(PyObject *intobj, PyDateTime_Delta *delta)
if (pyus_in == NULL)
return NULL;
- pyus_out = PyNumber_Multiply(pyus_in, intobj);
+ pyus_out = PyNumber_Multiply(intobj, pyus_in);
Py_DECREF(pyus_in);
if (pyus_out == NULL)
return NULL;
@@ -2297,13 +2304,12 @@ delta_divmod(PyObject *left, PyObject *right)
return NULL;
}
- divmod = PyNumber_Divmod(pyus_left, pyus_right);
+ divmod = checked_divmod(pyus_left, pyus_right);
Py_DECREF(pyus_left);
Py_DECREF(pyus_right);
if (divmod == NULL)
return NULL;
- assert(PyTuple_Size(divmod) == 2);
delta = microseconds_to_delta(PyTuple_GET_ITEM(divmod, 1));
if (delta == NULL) {
Py_DECREF(divmod);
@@ -2334,13 +2340,11 @@ accum(const char* tag, PyObject *sofar, PyObject *num, PyObject *factor,
assert(num != NULL);
if (PyLong_Check(num)) {
- prod = PyNumber_Multiply(factor, num);
+ prod = PyNumber_Multiply(num, factor);
if (prod == NULL)
return NULL;
- assert(PyLong_CheckExact(prod));
sum = PyNumber_Add(sofar, prod);
Py_DECREF(prod);
- assert(sum == NULL || PyLong_CheckExact(sum));
return sum;
}
@@ -2398,7 +2402,6 @@ accum(const char* tag, PyObject *sofar, PyObject *num, PyObject *factor,
Py_DECREF(sum);
Py_DECREF(x);
*leftover += fracpart;
- assert(y == NULL || PyLong_CheckExact(y));
return y;
}