Skip to content

Commit 691df49

Browse files
committed
Handle overflow in interval parsing
1 parent 3b665d3 commit 691df49

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

psycopg/typecast_datetime.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,19 @@ typecast_PYINTERVAL_cast(const char *str, Py_ssize_t len, PyObject *curs)
237237

238238
case '0': case '1': case '2': case '3': case '4':
239239
case '5': case '6': case '7': case '8': case '9':
240-
v = v * 10 + (*str - '0');
240+
{
241+
long v1;
242+
v1 = v * 10 + (*str - '0');
243+
/* detect either a rollover, happening if v is really too short,
244+
* or too big value. On Win where long == int the 2nd check
245+
* is useless. */
246+
if (v1 < v || v1 > (long)INT_MAX) {
247+
PyErr_SetString(
248+
PyExc_OverflowError, "interval component too big");
249+
return NULL;
250+
}
251+
v = v1;
252+
}
241253
if (part == 6) {
242254
denom *= 10;
243255
}
@@ -308,7 +320,7 @@ typecast_PYINTERVAL_cast(const char *str, Py_ssize_t len, PyObject *curs)
308320
} while (denom < 1000000L);
309321
}
310322
else if (denom > 1000000L) {
311-
micros = (long)((double)micros * 1000000.0 / denom);
323+
micros = (long)round((double)micros / denom * 1000000.0);
312324
}
313325
}
314326

tests/test_dates.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,24 @@ def test_micros_rounding(self):
373373
t = self.execute("select '0.0000006'::interval")
374374
self.assertEqual(total_seconds(t), 1e-6)
375375

376+
def test_interval_overflow(self):
377+
cur = self.conn.cursor()
378+
# hack a cursor to receive values too extreme to be represented
379+
# but still I want an error, not a random number
380+
psycopg2.extensions.register_type(
381+
psycopg2.extensions.new_type(
382+
psycopg2.STRING.values, 'WAT', psycopg2.extensions.INTERVAL),
383+
cur)
384+
385+
def f(val):
386+
cur.execute("select '%s'::text" % val)
387+
return cur.fetchone()[0]
388+
389+
self.assertRaises(OverflowError, f, '100000000000000000:00:00')
390+
self.assertRaises(OverflowError, f, '00:100000000000000000:00:00')
391+
self.assertRaises(OverflowError, f, '00:00:100000000000000000:00')
392+
self.assertRaises(OverflowError, f, '00:00:00.100000000000000000')
393+
376394

377395
# Only run the datetime tests if psycopg was compiled with support.
378396
if not hasattr(psycopg2.extensions, 'PYDATETIME'):

0 commit comments

Comments
 (0)