bpo-35021: Fix assertion failures in _datetimemodule.c. (GH-10039) · python/cpython@7a0d964 (original) (raw)
`@@ -1542,6 +1542,29 @@ delta_to_microseconds(PyDateTime_Delta *self)
`
1542
1542
`return result;
`
1543
1543
`}
`
1544
1544
``
``
1545
`+
static PyObject *
`
``
1546
`+
checked_divmod(PyObject *a, PyObject *b)
`
``
1547
`+
{
`
``
1548
`+
PyObject *result = PyNumber_Divmod(a, b);
`
``
1549
`+
if (result != NULL) {
`
``
1550
`+
if (!PyTuple_Check(result)) {
`
``
1551
`+
PyErr_Format(PyExc_TypeError,
`
``
1552
`+
"divmod() returned non-tuple (type %.200s)",
`
``
1553
`+
result->ob_type->tp_name);
`
``
1554
`+
Py_DECREF(result);
`
``
1555
`+
return NULL;
`
``
1556
`+
}
`
``
1557
`+
if (PyTuple_GET_SIZE(result) != 2) {
`
``
1558
`+
PyErr_Format(PyExc_TypeError,
`
``
1559
`+
"divmod() returned a tuple of size %zd",
`
``
1560
`+
PyTuple_GET_SIZE(result));
`
``
1561
`+
Py_DECREF(result);
`
``
1562
`+
return NULL;
`
``
1563
`+
}
`
``
1564
`+
}
`
``
1565
`+
return result;
`
``
1566
`+
}
`
``
1567
+
1545
1568
`/* Convert a number of us (as a Python int) to a timedelta.
`
1546
1569
` */
`
1547
1570
`static PyObject *
`
`@@ -1550,70 +1573,49 @@ microseconds_to_delta_ex(PyObject *pyus, PyTypeObject *type)
`
1550
1573
`int us;
`
1551
1574
`int s;
`
1552
1575
`int d;
`
1553
``
`-
long temp;
`
1554
1576
``
1555
1577
`PyObject *tuple = NULL;
`
1556
1578
`PyObject *num = NULL;
`
1557
1579
`PyObject *result = NULL;
`
1558
1580
``
1559
``
`-
assert(PyLong_CheckExact(pyus));
`
1560
``
`-
tuple = PyNumber_Divmod(pyus, us_per_second);
`
1561
``
`-
if (tuple == NULL)
`
``
1581
`+
tuple = checked_divmod(pyus, us_per_second);
`
``
1582
`+
if (tuple == NULL) {
`
1562
1583
` goto Done;
`
``
1584
`+
}
`
1563
1585
``
1564
``
`-
num = PyTuple_GetItem(tuple, 1); /* us */
`
1565
``
`-
if (num == NULL)
`
1566
``
`-
goto Done;
`
1567
``
`-
temp = PyLong_AsLong(num);
`
``
1586
`+
num = PyTuple_GET_ITEM(tuple, 1); /* us */
`
``
1587
`+
us = _PyLong_AsInt(num);
`
1568
1588
`num = NULL;
`
1569
``
`-
if (temp == -1 && PyErr_Occurred())
`
1570
``
`-
goto Done;
`
1571
``
`-
assert(0 <= temp && temp < 1000000);
`
1572
``
`-
us = (int)temp;
`
1573
``
`-
if (us < 0) {
`
1574
``
`-
/* The divisor was positive, so this must be an error. */
`
1575
``
`-
assert(PyErr_Occurred());
`
``
1589
`+
if (us == -1 && PyErr_Occurred()) {
`
1576
1590
` goto Done;
`
1577
1591
` }
`
``
1592
`+
if (!(0 <= us && us < 1000000)) {
`
``
1593
`+
goto BadDivmod;
`
``
1594
`+
}
`
1578
1595
``
1579
``
`-
num = PyTuple_GetItem(tuple, 0); /* leftover seconds */
`
1580
``
`-
if (num == NULL)
`
1581
``
`-
goto Done;
`
``
1596
`+
num = PyTuple_GET_ITEM(tuple, 0); /* leftover seconds */
`
1582
1597
`Py_INCREF(num);
`
1583
1598
`Py_DECREF(tuple);
`
1584
1599
``
1585
``
`-
tuple = PyNumber_Divmod(num, seconds_per_day);
`
``
1600
`+
tuple = checked_divmod(num, seconds_per_day);
`
1586
1601
`if (tuple == NULL)
`
1587
1602
` goto Done;
`
1588
1603
`Py_DECREF(num);
`
1589
1604
``
1590
``
`-
num = PyTuple_GetItem(tuple, 1); /* seconds */
`
1591
``
`-
if (num == NULL)
`
1592
``
`-
goto Done;
`
1593
``
`-
temp = PyLong_AsLong(num);
`
``
1605
`+
num = PyTuple_GET_ITEM(tuple, 1); /* seconds */
`
``
1606
`+
s = _PyLong_AsInt(num);
`
1594
1607
`num = NULL;
`
1595
``
`-
if (temp == -1 && PyErr_Occurred())
`
1596
``
`-
goto Done;
`
1597
``
`-
assert(0 <= temp && temp < 24*3600);
`
1598
``
`-
s = (int)temp;
`
1599
``
-
1600
``
`-
if (s < 0) {
`
1601
``
`-
/* The divisor was positive, so this must be an error. */
`
1602
``
`-
assert(PyErr_Occurred());
`
``
1608
`+
if (s == -1 && PyErr_Occurred()) {
`
1603
1609
` goto Done;
`
1604
1610
` }
`
``
1611
`+
if (!(0 <= s && s < 24*3600)) {
`
``
1612
`+
goto BadDivmod;
`
``
1613
`+
}
`
1605
1614
``
1606
``
`-
num = PyTuple_GetItem(tuple, 0); /* leftover days */
`
1607
``
`-
if (num == NULL)
`
1608
``
`-
goto Done;
`
``
1615
`+
num = PyTuple_GET_ITEM(tuple, 0); /* leftover days */
`
1609
1616
`Py_INCREF(num);
`
1610
``
`-
temp = PyLong_AsLong(num);
`
1611
``
`-
if (temp == -1 && PyErr_Occurred())
`
1612
``
`-
goto Done;
`
1613
``
`-
d = (int)temp;
`
1614
``
`-
if ((long)d != temp) {
`
1615
``
`-
PyErr_SetString(PyExc_OverflowError, "normalized days too "
`
1616
``
`-
"large to fit in a C int");
`
``
1617
`+
d = _PyLong_AsInt(num);
`
``
1618
`+
if (d == -1 && PyErr_Occurred()) {
`
1617
1619
` goto Done;
`
1618
1620
` }
`
1619
1621
`result = new_delta_ex(d, s, us, 0, type);
`
`@@ -1622,6 +1624,11 @@ microseconds_to_delta_ex(PyObject *pyus, PyTypeObject *type)
`
1622
1624
`Py_XDECREF(tuple);
`
1623
1625
`Py_XDECREF(num);
`
1624
1626
`return result;
`
``
1627
+
``
1628
`+
BadDivmod:
`
``
1629
`+
PyErr_SetString(PyExc_TypeError,
`
``
1630
`+
"divmod() returned a value out of range");
`
``
1631
`+
goto Done;
`
1625
1632
`}
`
1626
1633
``
1627
1634
`#define microseconds_to_delta(pymicros) \
`
`@@ -1638,7 +1645,7 @@ multiply_int_timedelta(PyObject *intobj, PyDateTime_Delta *delta)
`
1638
1645
`if (pyus_in == NULL)
`
1639
1646
`return NULL;
`
1640
1647
``
1641
``
`-
pyus_out = PyNumber_Multiply(pyus_in, intobj);
`
``
1648
`+
pyus_out = PyNumber_Multiply(intobj, pyus_in);
`
1642
1649
`Py_DECREF(pyus_in);
`
1643
1650
`if (pyus_out == NULL)
`
1644
1651
`return NULL;
`
`@@ -2073,13 +2080,12 @@ delta_divmod(PyObject *left, PyObject *right)
`
2073
2080
`return NULL;
`
2074
2081
` }
`
2075
2082
``
2076
``
`-
divmod = PyNumber_Divmod(pyus_left, pyus_right);
`
``
2083
`+
divmod = checked_divmod(pyus_left, pyus_right);
`
2077
2084
`Py_DECREF(pyus_left);
`
2078
2085
`Py_DECREF(pyus_right);
`
2079
2086
`if (divmod == NULL)
`
2080
2087
`return NULL;
`
2081
2088
``
2082
``
`-
assert(PyTuple_Size(divmod) == 2);
`
2083
2089
`delta = microseconds_to_delta(PyTuple_GET_ITEM(divmod, 1));
`
2084
2090
`if (delta == NULL) {
`
2085
2091
`Py_DECREF(divmod);
`
`@@ -2110,13 +2116,11 @@ accum(const char* tag, PyObject *sofar, PyObject *num, PyObject *factor,
`
2110
2116
`assert(num != NULL);
`
2111
2117
``
2112
2118
`if (PyLong_Check(num)) {
`
2113
``
`-
prod = PyNumber_Multiply(factor, num);
`
``
2119
`+
prod = PyNumber_Multiply(num, factor);
`
2114
2120
`if (prod == NULL)
`
2115
2121
`return NULL;
`
2116
``
`-
assert(PyLong_CheckExact(prod));
`
2117
2122
`sum = PyNumber_Add(sofar, prod);
`
2118
2123
`Py_DECREF(prod);
`
2119
``
`-
assert(sum == NULL || PyLong_CheckExact(sum));
`
2120
2124
`return sum;
`
2121
2125
` }
`
2122
2126
``
`@@ -2174,7 +2178,6 @@ accum(const char* tag, PyObject *sofar, PyObject *num, PyObject *factor,
`
2174
2178
`Py_DECREF(sum);
`
2175
2179
`Py_DECREF(x);
`
2176
2180
`*leftover += fracpart;
`
2177
``
`-
assert(y == NULL || PyLong_CheckExact(y));
`
2178
2181
`return y;
`
2179
2182
` }
`
2180
2183
``