Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit feec453

Browse files
committed
Bug 1003935: xrange overflows
Added XXX comment about why the undocumented PyRange_New() API function is too broken to be worth the considerable pain of repairing. Changed range_new() to stop using PyRange_New(). This fixes a variety of bogus errors. Nothing in the core uses PyRange_New() now. Documented that xrange() is intended to be simple and fast, and that CPython restricts its arguments, and length of its result sequence, to native C longs. Added some tests that failed before the patch, and repaired a test that relied on a bogus OverflowError getting raised.
1 parent d976ab7 commit feec453

3 files changed

Lines changed: 37 additions & 11 deletions

File tree

Doc/lib/libfuncs.tex

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ \section{Built-in Functions \label{built-in-funcs}}
7979

8080
\indexii{Boolean}{type}
8181
\versionadded{2.2.1}
82-
\versionchanged[If no argument is given, this function returns
82+
\versionchanged[If no argument is given, this function returns
8383
\constant{False}]{2.3}
8484
\end{funcdesc}
8585

@@ -379,7 +379,7 @@ \section{Built-in Functions \label{built-in-funcs}}
379379
that differentiate between binary and text files (else it is
380380
ignored). If the file cannot be opened, \exception{IOError} is
381381
raised.
382-
382+
383383
In addition to the standard \cfunction{fopen()} values \var{mode}
384384
may be \code{'U'} or \code{'rU'}. If Python is built with universal
385385
newline support (the default) the file is opened as a text file, but
@@ -392,7 +392,7 @@ \section{Built-in Functions \label{built-in-funcs}}
392392
\var{mode} \code{'U'} is the same as normal text mode. Note that
393393
file objects so opened also have an attribute called
394394
\member{newlines} which has a value of \code{None} (if no newlines
395-
have yet been seen), \code{'\e n'}, \code{'\e r'}, \code{'\e r\e n'},
395+
have yet been seen), \code{'\e n'}, \code{'\e r'}, \code{'\e r\e n'},
396396
or a tuple containing all the newline types seen.
397397

398398
If \var{mode} is omitted, it defaults to \code{'r'}. When opening a
@@ -459,7 +459,7 @@ \section{Built-in Functions \label{built-in-funcs}}
459459
the inner sets should also be \class{frozenset} objects. If
460460
\var{iterable} is not specified, returns a new empty set,
461461
\code{frozenset([])}.
462-
\versionadded{2.4}
462+
\versionadded{2.4}
463463
\end{funcdesc}
464464

465465
\begin{funcdesc}{getattr}{object, name\optional{, default}}
@@ -659,7 +659,7 @@ \section{Built-in Functions \label{built-in-funcs}}
659659
\end{funcdesc}
660660

661661
\begin{funcdesc}{object}{}
662-
Return a new featureless object. \function{object()} is a base
662+
Return a new featureless object. \function{object()} is a base
663663
for all new style classes. It has the methods that are common
664664
to all instances of new style classes.
665665
\versionadded{2.2}
@@ -901,7 +901,7 @@ \section{Built-in Functions \label{built-in-funcs}}
901901
must be immutable. To represent sets of sets, the inner sets should
902902
be \class{frozenset} objects. If \var{iterable} is not specified,
903903
returns a new empty set, \code{set([])}.
904-
\versionadded{2.4}
904+
\versionadded{2.4}
905905
\end{funcdesc}
906906

907907
\begin{funcdesc}{setattr}{object, name, value}
@@ -931,7 +931,7 @@ \section{Built-in Functions \label{built-in-funcs}}
931931
Return a new sorted list from the items in \var{iterable}.
932932
The optional arguments \var{cmp}, \var{key}, and \var{reverse}
933933
have the same meaning as those for the \method{list.sort()} method.
934-
\versionadded{2.4}
934+
\versionadded{2.4}
935935
\end{funcdesc}
936936

937937
\begin{funcdesc}{staticmethod}{function}
@@ -1099,6 +1099,12 @@ \section{Built-in Functions \label{built-in-funcs}}
10991099
them) except when a very large range is used on a memory-starved
11001100
machine or when all of the range's elements are never used (such as
11011101
when the loop is usually terminated with \keyword{break}).
1102+
1103+
\note{\function{xrange()} is intended to be simple and fast.
1104+
Implementations may impose restrictions to achieve this.
1105+
The C implementation of Python restricts all arguments to
1106+
native C longs ("short" Python integers), and also requires
1107+
that that number of elements fit in a native C long.}
11021108
\end{funcdesc}
11031109

11041110
\begin{funcdesc}{zip}{\optional{seq1, \moreargs}}
@@ -1114,11 +1120,11 @@ \section{Built-in Functions \label{built-in-funcs}}
11141120

11151121
\versionchanged[Formerly, \function{zip()} required at least one argument
11161122
and \code{zip()} raised a \exception{TypeError} instead of returning
1117-
an empty list.]{2.4}
1123+
an empty list.]{2.4}
11181124
\end{funcdesc}
11191125

11201126

1121-
% ---------------------------------------------------------------------------
1127+
% ---------------------------------------------------------------------------
11221128

11231129

11241130
\section{Non-essential Built-in Functions \label{non-essential-built-in-funcs}}

Lib/test/test_xrange.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,15 @@ def test_xrange(self):
4848
self.assertRaises(TypeError, xrange, 0, "spam")
4949
self.assertRaises(TypeError, xrange, 0, 42, "spam")
5050

51-
self.assertRaises(OverflowError, xrange, 0, sys.maxint, sys.maxint-1)
51+
self.assertEqual(len(xrange(0, sys.maxint, sys.maxint-1)), 2)
52+
5253
self.assertRaises(OverflowError, xrange, -sys.maxint, sys.maxint)
5354
self.assertRaises(OverflowError, xrange, 0, 2*sys.maxint)
5455

56+
self.assertEqual(len(xrange(-sys.maxint, sys.maxint, 2)),
57+
sys.maxint)
58+
self.assertRaises(OverflowError, xrange, -sys.maxint-1, sys.maxint, 2)
59+
5560
def test_main():
5661
test.test_support.run_unittest(XrangeTest)
5762

Objects/rangeobject.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ typedef struct {
99
long len;
1010
} rangeobject;
1111

12+
/* XXX PyRange_New should be deprecated. It's not documented. It's not
13+
* used in the core. Its error-checking is akin to Swiss cheese: accepts
14+
* step == 0; accepts len < 0; ignores that (len - 1) * step may overflow;
15+
* raises a baffling "integer addition" exception if it thinks the last
16+
* item is "too big"; and doesn't compute whether "last item is too big"
17+
* correctly even if the multiplication doesn't overflow.
18+
*/
1219
PyObject *
1320
PyRange_New(long start, long len, long step, int reps)
1421
{
@@ -79,6 +86,7 @@ get_len_of_range(long lo, long hi, long step)
7986
static PyObject *
8087
range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
8188
{
89+
rangeobject *obj;
8290
long ilow = 0, ihigh = 0, istep = 1;
8391
long n;
8492

@@ -107,7 +115,14 @@ range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
107115
"xrange() result has too many items");
108116
return NULL;
109117
}
110-
return PyRange_New(ilow, n, istep, 1);
118+
119+
obj = PyObject_New(rangeobject, &PyRange_Type);
120+
if (obj == NULL)
121+
return NULL;
122+
obj->start = ilow;
123+
obj->len = n;
124+
obj->step = istep;
125+
return (PyObject *) obj;
111126
}
112127

113128
PyDoc_STRVAR(range_doc,

0 commit comments

Comments
 (0)