Ticket #20368: 20368fix-against-56d6fdbbf50b29bd162fd5ab3296a25127d7af65.diff

File 20368fix-against-56d6fdbbf50b29bd162fd5ab3296a25127d7af65.diff, 6.1 KB (added by jakacki, 23 months ago)

Patch against [56d6fdbbf50b29bd162fd5ab3296a25127d7af65]

  • django/template/defaultfilters.py

    diff --git a/django/template/defaultfilters.py b/django/template/defaultfilters.py
    index 4201cfe..e0bee53 100644
    a b def force_escape(value): 
    414414    """
    415415    return escape(value)
    416416
     417@register.filter(is_safe=True)
     418@stringfilter
     419def nonraising_force_escape(value):
     420    """
     421    Escapes a string's HTML. This returns a new string containing the escaped
     422    characters, or in case of exception in force_escape()
     423    (in particular MemoryError), a unicode string notifying
     424    about the exception. Never raises any exception derived from Exception.
     425    """
     426    try:
     427        return force_escape(value)
     428    except Exception, e:
     429        return u"cannot render value due to exception in force_escape(): %s" % e.__class__.__name__
     430
    417431@register.filter("linebreaks", is_safe=True, needs_autoescape=True)
    418432@stringfilter
    419433def linebreaks_filter(value, autoescape=None):
  • django/views/debug.py

    diff --git a/django/views/debug.py b/django/views/debug.py
    index 10c07e8..a738f4f 100644
    a b from django.core.exceptions import ImproperlyConfigured 
    1111from django.http import (HttpResponse, HttpResponseServerError,
    1212    HttpResponseNotFound, HttpRequest, build_request_repr)
    1313from django.template import Template, Context, TemplateDoesNotExist
    14 from django.template.defaultfilters import force_escape, pprint
     14from django.template.defaultfilters import nonraising_force_escape, pprint
    1515from django.utils.html import escape
    1616from django.utils.encoding import force_bytes, smart_text
    1717from django.utils.module_loading import import_by_path
    class ExceptionReporter(object): 
    246246        frames = self.get_traceback_frames()
    247247        for i, frame in enumerate(frames):
    248248            if 'vars' in frame:
    249                 frame['vars'] = [(k, force_escape(pprint(v))) for k, v in frame['vars']]
     249                frame['vars'] = [(k, nonraising_force_escape(pprint(v)))
     250                    for k, v in frame['vars']]
    250251            frames[i] = frame
    251252
    252253        unicode_hint = ''
    TECHNICAL_500_TEMPLATE = """ 
    584585<body>
    585586<div id="summary">
    586587  <h1>{% if exception_type %}{{ exception_type }}{% else %}Report{% endif %}{% if request %} at {{ request.path_info|escape }}{% endif %}</h1>
    587   <pre class="exception_value">{% if exception_value %}{{ exception_value|force_escape }}{% else %}No exception supplied{% endif %}</pre>
     588  <pre class="exception_value">{% if exception_value %}{{ exception_value|nonraising_force_escape }}{% else %}No exception supplied{% endif %}</pre>
    588589  <table class="meta">
    589590{% if request %}
    590591    <tr>
    TECHNICAL_500_TEMPLATE = """ 
    609610{% if exception_type and exception_value %}
    610611    <tr>
    611612      <th>Exception Value:</th>
    612       <td><pre>{{ exception_value|force_escape }}</pre></td>
     613      <td><pre>{{ exception_value|nonraising_force_escape }}</pre></td>
    613614    </tr>
    614615{% endif %}
    615616{% if lastframe %}
    TECHNICAL_500_TEMPLATE = """ 
    639640{% if unicode_hint %}
    640641<div id="unicode-hint">
    641642    <h2>Unicode error hint</h2>
    642     <p>The string that could not be encoded/decoded was: <strong>{{ unicode_hint|force_escape }}</strong></p>
     643    <p>The string that could not be encoded/decoded was: <strong>{{ unicode_hint|nonraising_force_escape }}</strong></p>
    643644</div>
    644645{% endif %}
    645646{% if template_does_not_exist %}
    TECHNICAL_500_TEMPLATE = """ 
    717718              <tbody>
    718719                {% for var in frame.vars|dictsort:"0" %}
    719720                  <tr>
    720                     <td>{{ var.0|force_escape }}</td>
     721                    <td>{{ var.0|nonraising_force_escape }}</td>
    721722                    <td class="code"><pre>{{ var.1 }}</pre></td>
    722723                  </tr>
    723724                {% endfor %}
    Traceback: 
    770771{% if frame.context_line %}  {{ frame.lineno }}. {{ frame.context_line|escape }}{% endif %}
    771772{% endfor %}
    772773Exception Type: {{ exception_type|escape }}{% if request %} at {{ request.path_info|escape }}{% endif %}
    773 Exception Value: {{ exception_value|force_escape }}
     774Exception Value: {{ exception_value|nonraising_force_escape }}
    774775</textarea>
    775776  <br><br>
    776777  <input type="submit" value="Share this traceback on a public Web site">
  • tests/view_tests/tests/test_debug.py

    diff --git a/tests/view_tests/tests/test_debug.py b/tests/view_tests/tests/test_debug.py
    index a84b419..708d9e3 100644
    a b from django.test.utils import (override_settings, setup_test_template_loader, 
    1616    restore_template_loaders)
    1717from django.utils.encoding import force_text, force_bytes
    1818from django.views.debug import ExceptionReporter
     19from django.template import defaultfilters
    1920
    2021from .. import BrokenException, except_args
    2122from ..views import (sensitive_view, non_sensitive_view, paranoid_view,
    class ExceptionReporterTests(TestCase): 
    105106        self.assertIn('<h2>Request information</h2>', html)
    106107        self.assertNotIn('<p>Request data not supplied</p>', html)
    107108
     109    def test_request_and_exception_when_escaping_raises(self):
     110        "Complete rendering of exception report if escaping raises exception"
     111        # specifically if it raises MemoryError
     112       
     113        try:
     114            request = self.rf.get('/test_view/')
     115            raise ValueError("Can't find my keys")
     116        except ValueError:
     117            exc_type, exc_value, tb = sys.exc_info()
     118       
     119        def mock_escape_that_raises(*args, **kwargs):
     120            raise MemoryError()
     121           
     122        orig_escape = defaultfilters.escape
     123        try:
     124            defaultfilters.escape = mock_escape_that_raises
     125            reporter = ExceptionReporter(request, exc_type, exc_value, tb)
     126            html = reporter.get_traceback_html()
     127            self.assertIn('<h1>ValueError at /test_view/</h1>', html)
     128            self.assertIn('<pre class="exception_value">cannot render value due to exception in force_escape(): MemoryError</pre>', html)
     129        finally:
     130            defaultfilters.escape = orig_escape
     131
    108132    def test_no_request(self):
    109133        "An exception report can be generated without request"
    110134        try:
Back to Top