sandbox uses xrange on Python 2
diff --git a/CHANGES.rst b/CHANGES.rst
index 78e1329..8b7c7a5 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -5,9 +5,12 @@
Version 2.10.2
--------------
-_Unreleased_
+Unreleased
-- Fix Python 3.7 deprecation warnings.
+- Fix Python 3.7 deprecation warnings.
+- Using ``range`` in the sandboxed environment uses ``xrange`` on
+ Python 2 to avoid memory use. #933
+
Version 2.10.1
--------------
diff --git a/jinja2/sandbox.py b/jinja2/sandbox.py
index 97d3d21..08c22f4 100644
--- a/jinja2/sandbox.py
+++ b/jinja2/sandbox.py
@@ -16,7 +16,7 @@
import operator
from jinja2.environment import Environment
from jinja2.exceptions import SecurityError
-from jinja2._compat import string_types, PY2, abc
+from jinja2._compat import string_types, PY2, abc, range_type
from jinja2.utils import Markup
from markupsafe import EscapeFormatter
@@ -146,10 +146,14 @@
"""A range that can't generate ranges with a length of more than
MAX_RANGE items.
"""
- rng = range(*args)
+ rng = range_type(*args)
+
if len(rng) > MAX_RANGE:
- raise OverflowError('range too big, maximum size for range is %d' %
- MAX_RANGE)
+ raise OverflowError(
+ "Range too big. The sandbox blocks ranges larger than"
+ " MAX_RANGE (%d)." % MAX_RANGE
+ )
+
return rng
diff --git a/tests/test_api.py b/tests/test_api.py
index 5708144..26dd4da 100644
--- a/tests/test_api.py
+++ b/tests/test_api.py
@@ -68,7 +68,7 @@
c.next()
assert c.current == 2
c.reset()
- assert c.current == 1
+ assert c.current == 1
def test_expressions(self, env):
expr = env.compile_expression("foo")
@@ -104,6 +104,15 @@
t = env.from_string('{{ foo }}')
assert t.render(foo='<foo>') == '<foo>'
+ def test_sandbox_max_range(self, env):
+ from jinja2.sandbox import SandboxedEnvironment, MAX_RANGE
+
+ env = SandboxedEnvironment()
+ t = env.from_string("{% for item in range(total) %}{{ item }}{% endfor %}")
+
+ with pytest.raises(OverflowError):
+ t.render(total=MAX_RANGE + 1)
+
@pytest.mark.api
@pytest.mark.meta