Fixed #17133 -- Properly handled successive slashes in incoming requests

Thanks gjanee@ucop.edu for the report and Tim Graham for the review.
This commit is contained in:
Claude Paroz 2015-10-23 14:53:32 +02:00
parent 494b7986a3
commit 10ace52a41
3 changed files with 33 additions and 0 deletions

View File

@ -3,6 +3,7 @@ from __future__ import unicode_literals
import cgi import cgi
import codecs import codecs
import logging import logging
import re
import sys import sys
from io import BytesIO from io import BytesIO
from threading import Lock from threading import Lock
@ -21,6 +22,8 @@ logger = logging.getLogger('django.request')
# encode() and decode() expect the charset to be a native string. # encode() and decode() expect the charset to be a native string.
ISO_8859_1, UTF_8 = str('iso-8859-1'), str('utf-8') ISO_8859_1, UTF_8 = str('iso-8859-1'), str('utf-8')
_slashes_re = re.compile(br'/+')
class LimitedStream(object): class LimitedStream(object):
''' '''
@ -218,6 +221,9 @@ def get_script_name(environ):
script_url = get_bytes_from_wsgi(environ, 'REDIRECT_URL', '') script_url = get_bytes_from_wsgi(environ, 'REDIRECT_URL', '')
if script_url: if script_url:
# mod_wsgi squashes multiple successive slashes in PATH_INFO,
# do the same with script_url before manipulating paths (#17133).
script_url = _slashes_re.sub(b'/', script_url)
path_info = get_bytes_from_wsgi(environ, 'PATH_INFO', '') path_info = get_bytes_from_wsgi(environ, 'PATH_INFO', '')
script_name = script_url[:-len(path_info)] if path_info else script_url script_name = script_url[:-len(path_info)] if path_info else script_url
else: else:

View File

@ -211,3 +211,14 @@ class ScriptNameTests(SimpleTestCase):
script_name = get_script_name({'SCRIPT_URL': '/foobar/', 'PATH_INFO': '/'}) script_name = get_script_name({'SCRIPT_URL': '/foobar/', 'PATH_INFO': '/'})
self.assertEqual(script_name, '/foobar') self.assertEqual(script_name, '/foobar')
def test_get_script_name_double_slashes(self):
"""
WSGI squashes multiple successive slashes in PATH_INFO, get_script_name
should take that into account when forming SCRIPT_NAME (#17133).
"""
script_name = get_script_name({
'SCRIPT_URL': '/mst/milestones//accounts/login//help',
'PATH_INFO': '/milestones/accounts/login/help',
})
self.assertEqual(script_name, '/mst')

View File

@ -104,6 +104,22 @@ class RequestsTests(SimpleTestCase):
}) })
self.assertEqual(request.path, '/PREFIX/somepath/') self.assertEqual(request.path, '/PREFIX/somepath/')
def test_wsgirequest_script_url_double_slashes(self):
"""
WSGI squashes multiple successive slashes in PATH_INFO, WSGIRequest
should take that into account when populating request.path and
request.META['SCRIPT_NAME'].
Refs #17133.
"""
request = WSGIRequest({
'SCRIPT_URL': '/mst/milestones//accounts/login//help',
'PATH_INFO': '/milestones/accounts/login/help',
'REQUEST_METHOD': 'get',
'wsgi.input': BytesIO(b''),
})
self.assertEqual(request.path, '/mst/milestones/accounts/login/help')
self.assertEqual(request.META['SCRIPT_NAME'], '/mst')
def test_wsgirequest_with_force_script_name(self): def test_wsgirequest_with_force_script_name(self):
""" """
Ensure that the FORCE_SCRIPT_NAME setting takes precedence over the Ensure that the FORCE_SCRIPT_NAME setting takes precedence over the