#22486: urlresolvers.reverse() security fix (1.5.6) breaks when a view is a 
partial
-----------------------------+--------------------
     Reporter:  rcoup        |      Owner:  nobody
         Type:  Bug          |     Status:  new
    Component:  Core (URLs)  |    Version:  1.5
     Severity:  Normal       |   Keywords:
 Triage Stage:  Unreviewed   |  Has patch:  0
Easy pickings:  0            |      UI/UX:  0
-----------------------------+--------------------
 The changes in the recent security fix for `reverse()`
 
[https://github.com/django/django/commit/8b93b31487d6d3b0fcbbd0498991ea0db9088054
 Fixed a remote code execution vulnerabilty in URL reversing]
 ([https://www.djangoproject.com/weblog/2014/apr/21/security/
 CVE-2014-0472]) break when any view in the urlpatterns is a functools
 partial.

 Django 1.5.6 / Py2.6.5 / Linux.

 pseudo-code:


 {{{
 # myapp/views.py
 def my_view(request, **kwargs):
      return HttpResponse(str(kwargs))

 my_view2 = functools.partial(my_view, some_arg=123)

 # myapp/urls.py
 urlpatterns = patterns('my_app.views',
    ('^some_view/$', 'normal_view'),  # a normal function/class view
    ('^breaks/$', 'my_view2'),        # partial-wrapped view
 )

 }}}

 Then

 {{{
 >>> from django.core.urlresolvers import reverse
 >>> reverse('my_app.some_view')
 django/core/urlresolvers.pyc in reverse(viewname, urlconf, args, kwargs,
 prefix, current_app)
     514             resolver = get_ns_resolver(ns_pattern, resolver)
     515
 --> 516     return iri_to_uri(resolver._reverse_with_prefix(view, prefix,
 *args, **kwargs))
     517
     518 reverse_lazy = lazy(reverse, str)

 django/core/urlresolvers.pyc in _reverse_with_prefix(self, lookup_view,
 _prefix, *args, **kwargs)
     393
     394         if not self._populated:
 --> 395             self._populate()
     396
     397         try:

 django/core/urlresolvers.pyc in _populate(self)
     285                 else:
     286                     parent = normalize(pattern.regex.pattern)
 --> 287                     for name in pattern.reverse_dict:
     288                         for matches, pat, defaults in
 pattern.reverse_dict.getlist(name):
     289                             new_matches = []

 django/core/urlresolvers.pyc in reverse_dict(self)
     310         language_code = get_language()
     311         if language_code not in self._reverse_dict:
 --> 312             self._populate()
     313         return self._reverse_dict[language_code]
     314

 django/core/urlresolvers.pyc in _populate(self)
     271                 callback = pattern._callback
     272                 if not hasattr(callback, '__name__'):
 --> 273                     lookup_str = callback.__module__ + "." +
 callback.__class__.__name__
     274                 else:
     275                     lookup_str = callback.__module__ + "." +
 callback.__name__

 AttributeError: 'functools.partial' object has no attribute '__module__'
 }}}

 Changing the view to use `functools.update_wrapper()` (as it probably
 should) and it works okay:

 {{{
 my_view2 = functools.partial(my_view, some_arg=123)
 functools.update_wrapper(my_view2, my_view)
 }}}

-- 
Ticket URL: <https://code.djangoproject.com/ticket/22486>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/048.11c7f3699d0175c225d5f4869311f56d%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to