Fixed integer overflow in interval typecaster

Close #512.
This commit is contained in:
Daniele Varrazzo 2017-02-24 02:10:27 +01:00
parent f5bd6063fc
commit 14fe3ad8c9
3 changed files with 9 additions and 4 deletions

1
NEWS
View File

@ -47,6 +47,7 @@ Bug fixes:
- Fixed error caused by missing decoding `~psycopg2.extras.LoggingConnection` - Fixed error caused by missing decoding `~psycopg2.extras.LoggingConnection`
(:ticket:`#483`). (:ticket:`#483`).
- Fixed integer overflow in :sql:`interval` seconds (:ticket:`#512`).
Other changes: Other changes:

View File

@ -220,10 +220,10 @@ typecast_PYTIME_cast(const char *str, Py_ssize_t len, PyObject *curs)
static PyObject * static PyObject *
typecast_PYINTERVAL_cast(const char *str, Py_ssize_t len, PyObject *curs) typecast_PYINTERVAL_cast(const char *str, Py_ssize_t len, PyObject *curs)
{ {
long years = 0, months = 0, days = 0; long years = 0, months = 0, days = 0, sec;
double hours = 0.0, minutes = 0.0, seconds = 0.0, hundredths = 0.0; double hours = 0.0, minutes = 0.0, seconds = 0.0, hundredths = 0.0;
double v = 0.0, sign = 1.0, denominator = 1.0; double v = 0.0, sign = 1.0, denominator = 1.0;
int part = 0, sec; int part = 0;
double micro; double micro;
if (str == NULL) { Py_RETURN_NONE; } if (str == NULL) { Py_RETURN_NONE; }
@ -318,8 +318,8 @@ typecast_PYINTERVAL_cast(const char *str, Py_ssize_t len, PyObject *curs)
days += years*365 + months*30; days += years*365 + months*30;
micro = (seconds - floor(seconds)) * 1000000.0; micro = (seconds - floor(seconds)) * 1000000.0;
sec = (int)floor(seconds); sec = (long)floor(seconds);
return PyObject_CallFunction((PyObject*)PyDateTimeAPI->DeltaType, "iii", return PyObject_CallFunction((PyObject*)PyDateTimeAPI->DeltaType, "lli",
days, sec, (int)round(micro)); days, sec, (int)round(micro));
} }

View File

@ -333,6 +333,10 @@ class DatetimeTests(ConnectingTestCase, CommonDatetimeTestsMixin):
t = self.execute("select '24:00+05:30'::timetz;") t = self.execute("select '24:00+05:30'::timetz;")
self.assertEqual(t, time(0, 0, tzinfo=FixedOffsetTimezone(330))) self.assertEqual(t, time(0, 0, tzinfo=FixedOffsetTimezone(330)))
def test_large_interval(self):
t = self.execute("select '999999:00:00'::interval")
self.assertEqual(t.days * 24 + t.seconds / 60.0 / 60, 999999)
# Only run the datetime tests if psycopg was compiled with support. # Only run the datetime tests if psycopg was compiled with support.
if not hasattr(psycopg2.extensions, 'PYDATETIME'): if not hasattr(psycopg2.extensions, 'PYDATETIME'):