summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Belopolsky <alexander.belopolsky@gmail.com>2010-05-27 22:03:53 (GMT)
committerAlexander Belopolsky <alexander.belopolsky@gmail.com>2010-05-27 22:03:53 (GMT)
commit3efc2fd479f024b70d9532cd4249ad6aaf8aba77 (patch)
tree844993b1a8a4fe39009f7c07065c9a8eff0502a2
parentdfe715e13612c32a531ea9c0e8869da929481b25 (diff)
downloadcpython-3efc2fd479f024b70d9532cd4249ad6aaf8aba77.zip
cpython-3efc2fd479f024b70d9532cd4249ad6aaf8aba77.tar.gz
cpython-3efc2fd479f024b70d9532cd4249ad6aaf8aba77.tar.bz2
Merged revisions 81568 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r81568 | alexander.belopolsky | 2010-05-27 17:42:58 -0400 (Thu, 27 May 2010) | 10 lines Merged revisions 81566 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r81566 | alexander.belopolsky | 2010-05-27 16:55:27 -0400 (Thu, 27 May 2010) | 3 lines Issue #7150: Raise OverflowError if the result of adding or subtracting timedelta from date or datetime falls outside of the MINYEAR:MAXYEAR range. ........ ................
-rw-r--r--Lib/test/test_datetime.py19
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/datetimemodule.c29
3 files changed, 29 insertions, 22 deletions
diff --git a/Lib/test/test_datetime.py b/Lib/test/test_datetime.py
index 8bf8420..ead8d70 100644
--- a/Lib/test/test_datetime.py
+++ b/Lib/test/test_datetime.py
@@ -700,15 +700,16 @@ class TestDate(HarmlessMixedComparison, unittest.TestCase):
def test_overflow(self):
tiny = self.theclass.resolution
- dt = self.theclass.min + tiny
- dt -= tiny # no problem
- self.assertRaises(OverflowError, dt.__sub__, tiny)
- self.assertRaises(OverflowError, dt.__add__, -tiny)
-
- dt = self.theclass.max - tiny
- dt += tiny # no problem
- self.assertRaises(OverflowError, dt.__add__, tiny)
- self.assertRaises(OverflowError, dt.__sub__, -tiny)
+ for delta in [tiny, timedelta(1), timedelta(2)]:
+ dt = self.theclass.min + delta
+ dt -= delta # no problem
+ self.assertRaises(OverflowError, dt.__sub__, delta)
+ self.assertRaises(OverflowError, dt.__add__, -delta)
+
+ dt = self.theclass.max - delta
+ dt += delta # no problem
+ self.assertRaises(OverflowError, dt.__add__, delta)
+ self.assertRaises(OverflowError, dt.__sub__, -delta)
def test_fromtimestamp(self):
import time
diff --git a/Misc/NEWS b/Misc/NEWS
index 5de0ca3..3c4aa76 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -54,6 +54,9 @@ C-API
Library
-------
+- Issue #7150: Raise OverflowError if the result of adding or subtracting
+ timedelta from date or datetime falls outside of the MINYEAR:MAXYEAR range.
+
- Issue #4769: Fix main() function of the base64 module, use sys.stdin.buffer
and sys.stdout.buffer (instead of sys.stdin and sys.stdout) to use the bytes
API
diff --git a/Modules/datetimemodule.c b/Modules/datetimemodule.c
index 6235d6e..419eb7b 100644
--- a/Modules/datetimemodule.c
+++ b/Modules/datetimemodule.c
@@ -30,6 +30,7 @@
#define MINYEAR 1
#define MAXYEAR 9999
+#define MAXORDINAL 3652059 /* date(9999,12,31).toordinal() */
/* Nine decimal digits is easy to communicate, and leaves enough room
* so that two delta days can be added w/o fear of overflowing a signed
@@ -480,7 +481,7 @@ normalize_d_s_us(int *d, int *s, int *us)
* The input values must be such that the internals don't overflow.
* The way this routine is used, we don't get close.
*/
-static void
+static int
normalize_y_m_d(int *y, int *m, int *d)
{
int dim; /* # of days in month */
@@ -534,11 +535,23 @@ normalize_y_m_d(int *y, int *m, int *d)
else {
int ordinal = ymd_to_ord(*y, *m, 1) +
*d - 1;
- ord_to_ymd(ordinal, y, m, d);
+ if (ordinal < 1 || ordinal > MAXORDINAL) {
+ goto error;
+ } else {
+ ord_to_ymd(ordinal, y, m, d);
+ return 0;
+ }
}
}
assert(*m > 0);
assert(*d > 0);
+ if (MINYEAR <= *y && *y <= MAXYEAR)
+ return 0;
+ error:
+ PyErr_SetString(PyExc_OverflowError,
+ "date value out of range");
+ return -1;
+
}
/* Fiddle out-of-bounds months and days so that the result makes some kind
@@ -548,17 +561,7 @@ normalize_y_m_d(int *y, int *m, int *d)
static int
normalize_date(int *year, int *month, int *day)
{
- int result;
-
- normalize_y_m_d(year, month, day);
- if (MINYEAR <= *year && *year <= MAXYEAR)
- result = 0;
- else {
- PyErr_SetString(PyExc_OverflowError,
- "date value out of range");
- result = -1;
- }
- return result;
+ return normalize_y_m_d(year, month, day);
}
/* Force all the datetime fields into range. The parameters are both