| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -375,8 +375,14 @@ def test_pickling(self): | |||
| 375 | 375 | ||
| 376 | 376 | def test_iterator_pickling(self): | |
| 377 | 377 | testcases = [(13,), (0, 11), (-22, 10), (20, 3, -1), (13, 21, 3), | |
| 378 | - (-2, 2, 2), (2**31-3, 2**31-1), (2**33, 2**33+2), | ||
| 379 | - (2**63-3, 2**63-1), (2**65, 2**65+2)] | ||
| 378 | + (-2, 2, 2)] | ||
| 379 | + for M in 2**31, 2**63: | ||
| 380 | + testcases += [ | ||
| 381 | + (M-3, M-1), (4*M, 4*M+2), | ||
| 382 | + (M-2, M-1, 2), (-M+1, -M, -2), | ||
| 383 | + (1, 2, M-1), (-1, -2, -M), | ||
| 384 | + (1, M-1, M-1), (-1, -M, -M), | ||
| 385 | + ] | ||
| 380 | 386 | for proto in range(pickle.HIGHEST_PROTOCOL + 1): | |
| 381 | 387 | for t in testcases: | |
| 382 | 388 | with self.subTest(proto=proto, t=t): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1 @@ | |||
| 1 | + Fix integer overflow in pickling and copying the range iterator. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -895,22 +895,14 @@ get_len_of_range(long lo, long hi, long step) | |||
| 895 | 895 | is not representable as a C long, OverflowError is raised. */ | |
| 896 | 896 | ||
| 897 | 897 | static PyObject * | |
| 898 | - fast_range_iter(long start, long stop, long step) | ||
| 898 | + fast_range_iter(long start, long stop, long step, long len) | ||
| 899 | 899 | { | |
| 900 | 900 | rangeiterobject *it = PyObject_New(rangeiterobject, &PyRangeIter_Type); | |
| 901 | - unsigned long ulen; | ||
| 902 | 901 | if (it == NULL) | |
| 903 | 902 | return NULL; | |
| 904 | 903 | it->start = start; | |
| 905 | 904 | it->step = step; | |
| 906 | - ulen = get_len_of_range(start, stop, step); | ||
| 907 | - if (ulen > (unsigned long)LONG_MAX) { | ||
| 908 | - Py_DECREF(it); | ||
| 909 | - PyErr_SetString(PyExc_OverflowError, | ||
| 910 | - "range too large to represent as a range_iterator"); | ||
| 911 | - return NULL; | ||
| 912 | - } | ||
| 913 | - it->len = (long)ulen; | ||
| 905 | + it->len = len; | ||
| 914 | 906 | it->index = 0; | |
| 915 | 907 | return (PyObject *)it; | |
| 916 | 908 | } | |
@@ -1071,7 +1063,7 @@ range_iter(PyObject *seq) | |||
| 1071 | 1063 | rangeobject *r = (rangeobject *)seq; | |
| 1072 | 1064 | longrangeiterobject *it; | |
| 1073 | 1065 | long lstart, lstop, lstep; | |
| 1074 | - PyObject *int_it; | ||
| 1066 | + unsigned long ulen; | ||
| 1075 | 1067 | ||
| 1076 | 1068 | assert(PyRange_Check(seq)); | |
| 1077 | 1069 | ||
@@ -1092,12 +1084,22 @@ range_iter(PyObject *seq) | |||
| 1092 | 1084 | PyErr_Clear(); | |
| 1093 | 1085 | goto long_range; | |
| 1094 | 1086 | } | |
| 1095 | - int_it = fast_range_iter(lstart, lstop, lstep); | ||
| 1096 | - if (int_it == NULL && PyErr_ExceptionMatches(PyExc_OverflowError)) { | ||
| 1097 | - PyErr_Clear(); | ||
| 1087 | + ulen = get_len_of_range(lstart, lstop, lstep); | ||
| 1088 | + if (ulen > (unsigned long)LONG_MAX) { | ||
| 1098 | 1089 | goto long_range; | |
| 1099 | 1090 | } | |
| 1100 | - return (PyObject *)int_it; | ||
| 1091 | + /* check for potential overflow of lstart + ulen * lstep */ | ||
| 1092 | + if (ulen) { | ||
| 1093 | + if (lstep > 0) { | ||
| 1094 | + if (lstop > LONG_MAX - (lstep - 1)) | ||
| 1095 | + goto long_range; | ||
| 1096 | + } | ||
| 1097 | + else { | ||
| 1098 | + if (lstop < LONG_MIN + (-1 - lstep)) | ||
| 1099 | + goto long_range; | ||
| 1100 | + } | ||
| 1101 | + } | ||
| 1102 | + return fast_range_iter(lstart, lstop, lstep, (long)ulen); | ||
| 1101 | 1103 | ||
| 1102 | 1104 | long_range: | |
| 1103 | 1105 | it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type); | |
@@ -1183,7 +1185,7 @@ range_reverse(PyObject *seq, PyObject *Py_UNUSED(ignored)) | |||
| 1183 | 1185 | ||
| 1184 | 1186 | new_stop = lstart - lstep; | |
| 1185 | 1187 | new_start = (long)(new_stop + ulen * lstep); | |
| 1186 | - return fast_range_iter(new_start, new_stop, -lstep); | ||
| 1188 | + return fast_range_iter(new_start, new_stop, -lstep, (long)ulen); | ||
| 1187 | 1189 | ||
| 1188 | 1190 | long_range: | |
| 1189 | 1191 | it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments