bpo-35021: Fix assertion failures in _datetimemodule.c. (GH-10039) · python/cpython@d57ab8a (original) (raw)

`@@ -1783,6 +1783,29 @@ delta_to_microseconds(PyDateTime_Delta *self)

`

1783

1783

`return result;

`

1784

1784

`}

`

1785

1785

``

``

1786

`+

static PyObject *

`

``

1787

`+

checked_divmod(PyObject *a, PyObject *b)

`

``

1788

`+

{

`

``

1789

`+

PyObject *result = PyNumber_Divmod(a, b);

`

``

1790

`+

if (result != NULL) {

`

``

1791

`+

if (!PyTuple_Check(result)) {

`

``

1792

`+

PyErr_Format(PyExc_TypeError,

`

``

1793

`+

"divmod() returned non-tuple (type %.200s)",

`

``

1794

`+

result->ob_type->tp_name);

`

``

1795

`+

Py_DECREF(result);

`

``

1796

`+

return NULL;

`

``

1797

`+

}

`

``

1798

`+

if (PyTuple_GET_SIZE(result) != 2) {

`

``

1799

`+

PyErr_Format(PyExc_TypeError,

`

``

1800

`+

"divmod() returned a tuple of size %zd",

`

``

1801

`+

PyTuple_GET_SIZE(result));

`

``

1802

`+

Py_DECREF(result);

`

``

1803

`+

return NULL;

`

``

1804

`+

}

`

``

1805

`+

}

`

``

1806

`+

return result;

`

``

1807

`+

}

`

``

1808

+

1786

1809

`/* Convert a number of us (as a Python int) to a timedelta.

`

1787

1810

` */

`

1788

1811

`static PyObject *

`

`@@ -1791,70 +1814,49 @@ microseconds_to_delta_ex(PyObject *pyus, PyTypeObject *type)

`

1791

1814

`int us;

`

1792

1815

`int s;

`

1793

1816

`int d;

`

1794

``

`-

long temp;

`

1795

1817

``

1796

1818

`PyObject *tuple = NULL;

`

1797

1819

`PyObject *num = NULL;

`

1798

1820

`PyObject *result = NULL;

`

1799

1821

``

1800

``

`-

assert(PyLong_CheckExact(pyus));

`

1801

``

`-

tuple = PyNumber_Divmod(pyus, us_per_second);

`

1802

``

`-

if (tuple == NULL)

`

``

1822

`+

tuple = checked_divmod(pyus, us_per_second);

`

``

1823

`+

if (tuple == NULL) {

`

1803

1824

` goto Done;

`

``

1825

`+

}

`

1804

1826

``

1805

``

`-

num = PyTuple_GetItem(tuple, 1); /* us */

`

1806

``

`-

if (num == NULL)

`

1807

``

`-

goto Done;

`

1808

``

`-

temp = PyLong_AsLong(num);

`

``

1827

`+

num = PyTuple_GET_ITEM(tuple, 1); /* us */

`

``

1828

`+

us = _PyLong_AsInt(num);

`

1809

1829

`num = NULL;

`

1810

``

`-

if (temp == -1 && PyErr_Occurred())

`

1811

``

`-

goto Done;

`

1812

``

`-

assert(0 <= temp && temp < 1000000);

`

1813

``

`-

us = (int)temp;

`

1814

``

`-

if (us < 0) {

`

1815

``

`-

/* The divisor was positive, so this must be an error. */

`

1816

``

`-

assert(PyErr_Occurred());

`

``

1830

`+

if (us == -1 && PyErr_Occurred()) {

`

1817

1831

` goto Done;

`

1818

1832

` }

`

``

1833

`+

if (!(0 <= us && us < 1000000)) {

`

``

1834

`+

goto BadDivmod;

`

``

1835

`+

}

`

1819

1836

``

1820

``

`-

num = PyTuple_GetItem(tuple, 0); /* leftover seconds */

`

1821

``

`-

if (num == NULL)

`

1822

``

`-

goto Done;

`

``

1837

`+

num = PyTuple_GET_ITEM(tuple, 0); /* leftover seconds */

`

1823

1838

`Py_INCREF(num);

`

1824

1839

`Py_DECREF(tuple);

`

1825

1840

``

1826

``

`-

tuple = PyNumber_Divmod(num, seconds_per_day);

`

``

1841

`+

tuple = checked_divmod(num, seconds_per_day);

`

1827

1842

`if (tuple == NULL)

`

1828

1843

` goto Done;

`

1829

1844

`Py_DECREF(num);

`

1830

1845

``

1831

``

`-

num = PyTuple_GetItem(tuple, 1); /* seconds */

`

1832

``

`-

if (num == NULL)

`

1833

``

`-

goto Done;

`

1834

``

`-

temp = PyLong_AsLong(num);

`

``

1846

`+

num = PyTuple_GET_ITEM(tuple, 1); /* seconds */

`

``

1847

`+

s = _PyLong_AsInt(num);

`

1835

1848

`num = NULL;

`

1836

``

`-

if (temp == -1 && PyErr_Occurred())

`

1837

``

`-

goto Done;

`

1838

``

`-

assert(0 <= temp && temp < 24*3600);

`

1839

``

`-

s = (int)temp;

`

1840

``

-

1841

``

`-

if (s < 0) {

`

1842

``

`-

/* The divisor was positive, so this must be an error. */

`

1843

``

`-

assert(PyErr_Occurred());

`

``

1849

`+

if (s == -1 && PyErr_Occurred()) {

`

1844

1850

` goto Done;

`

1845

1851

` }

`

``

1852

`+

if (!(0 <= s && s < 24*3600)) {

`

``

1853

`+

goto BadDivmod;

`

``

1854

`+

}

`

1846

1855

``

1847

``

`-

num = PyTuple_GetItem(tuple, 0); /* leftover days */

`

1848

``

`-

if (num == NULL)

`

1849

``

`-

goto Done;

`

``

1856

`+

num = PyTuple_GET_ITEM(tuple, 0); /* leftover days */

`

1850

1857

`Py_INCREF(num);

`

1851

``

`-

temp = PyLong_AsLong(num);

`

1852

``

`-

if (temp == -1 && PyErr_Occurred())

`

1853

``

`-

goto Done;

`

1854

``

`-

d = (int)temp;

`

1855

``

`-

if ((long)d != temp) {

`

1856

``

`-

PyErr_SetString(PyExc_OverflowError, "normalized days too "

`

1857

``

`-

"large to fit in a C int");

`

``

1858

`+

d = _PyLong_AsInt(num);

`

``

1859

`+

if (d == -1 && PyErr_Occurred()) {

`

1858

1860

` goto Done;

`

1859

1861

` }

`

1860

1862

`result = new_delta_ex(d, s, us, 0, type);

`

`@@ -1863,6 +1865,11 @@ microseconds_to_delta_ex(PyObject *pyus, PyTypeObject *type)

`

1863

1865

`Py_XDECREF(tuple);

`

1864

1866

`Py_XDECREF(num);

`

1865

1867

`return result;

`

``

1868

+

``

1869

`+

BadDivmod:

`

``

1870

`+

PyErr_SetString(PyExc_TypeError,

`

``

1871

`+

"divmod() returned a value out of range");

`

``

1872

`+

goto Done;

`

1866

1873

`}

`

1867

1874

``

1868

1875

`#define microseconds_to_delta(pymicros) \

`

`@@ -1879,7 +1886,7 @@ multiply_int_timedelta(PyObject *intobj, PyDateTime_Delta *delta)

`

1879

1886

`if (pyus_in == NULL)

`

1880

1887

`return NULL;

`

1881

1888

``

1882

``

`-

pyus_out = PyNumber_Multiply(pyus_in, intobj);

`

``

1889

`+

pyus_out = PyNumber_Multiply(intobj, pyus_in);

`

1883

1890

`Py_DECREF(pyus_in);

`

1884

1891

`if (pyus_out == NULL)

`

1885

1892

`return NULL;

`

`@@ -2283,13 +2290,12 @@ delta_divmod(PyObject *left, PyObject *right)

`

2283

2290

`return NULL;

`

2284

2291

` }

`

2285

2292

``

2286

``

`-

divmod = PyNumber_Divmod(pyus_left, pyus_right);

`

``

2293

`+

divmod = checked_divmod(pyus_left, pyus_right);

`

2287

2294

`Py_DECREF(pyus_left);

`

2288

2295

`Py_DECREF(pyus_right);

`

2289

2296

`if (divmod == NULL)

`

2290

2297

`return NULL;

`

2291

2298

``

2292

``

`-

assert(PyTuple_Size(divmod) == 2);

`

2293

2299

`delta = microseconds_to_delta(PyTuple_GET_ITEM(divmod, 1));

`

2294

2300

`if (delta == NULL) {

`

2295

2301

`Py_DECREF(divmod);

`

`@@ -2320,13 +2326,11 @@ accum(const char* tag, PyObject *sofar, PyObject *num, PyObject *factor,

`

2320

2326

`assert(num != NULL);

`

2321

2327

``

2322

2328

`if (PyLong_Check(num)) {

`

2323

``

`-

prod = PyNumber_Multiply(factor, num);

`

``

2329

`+

prod = PyNumber_Multiply(num, factor);

`

2324

2330

`if (prod == NULL)

`

2325

2331

`return NULL;

`

2326

``

`-

assert(PyLong_CheckExact(prod));

`

2327

2332

`sum = PyNumber_Add(sofar, prod);

`

2328

2333

`Py_DECREF(prod);

`

2329

``

`-

assert(sum == NULL || PyLong_CheckExact(sum));

`

2330

2334

`return sum;

`

2331

2335

` }

`

2332

2336

``

`@@ -2384,7 +2388,6 @@ accum(const char* tag, PyObject *sofar, PyObject *num, PyObject *factor,

`

2384

2388

`Py_DECREF(sum);

`

2385

2389

`Py_DECREF(x);

`

2386

2390

`*leftover += fracpart;

`

2387

``

`-

assert(y == NULL || PyLong_CheckExact(y));

`

2388

2391

`return y;

`

2389

2392

` }

`

2390

2393

``