check if the header contains control characters

fix #1227
This commit is contained in:
benoitc 2016-03-18 23:15:26 +01:00
parent 52088be726
commit 1e10a02e73
2 changed files with 29 additions and 0 deletions

View File

@ -10,6 +10,8 @@ import re
import sys import sys
from gunicorn._compat import unquote_to_wsgi_str from gunicorn._compat import unquote_to_wsgi_str
from gunicorn.http.message import HEADER_RE
from gunicorn.http.errors import InvalidHeader, InvalidHeaderName
from gunicorn.six import string_types, binary_type, reraise from gunicorn.six import string_types, binary_type, reraise
from gunicorn import SERVER_SOFTWARE from gunicorn import SERVER_SOFTWARE
import gunicorn.util as util import gunicorn.util as util
@ -28,6 +30,7 @@ except ImportError:
BLKSIZE = 0x3FFFFFFF BLKSIZE = 0x3FFFFFFF
NORMALIZE_SPACE = re.compile(r'(?:\r\n)?[ \t]+') NORMALIZE_SPACE = re.compile(r'(?:\r\n)?[ \t]+')
HEADER_VALUE_RE = re.compile(r'[\x00-\x1F\x7F]')
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -264,6 +267,13 @@ class Response(object):
for name, value in headers: for name, value in headers:
if not isinstance(name, string_types): if not isinstance(name, string_types):
raise TypeError('%r is not a string' % name) raise TypeError('%r is not a string' % name)
if HEADER_RE.search(name):
raise InvalidHeaderName('%r' % name)
if HEADER_VALUE_RE.search(value):
raise InvalidHeader('%r' % value)
value = str(value).strip() value = str(value).strip()
lname = name.lower().strip() lname = name.lower().strip()
if lname == "content-length": if lname == "content-length":

View File

@ -1,10 +1,12 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
import t import t
import pytest
from gunicorn import util from gunicorn import util
from gunicorn.http.body import Body from gunicorn.http.body import Body
from gunicorn.http.wsgi import Response from gunicorn.http.wsgi import Response
from gunicorn.six import BytesIO from gunicorn.six import BytesIO
from gunicorn.http.errors import InvalidHeader, InvalidHeaderName
try: try:
import unittest.mock as mock import unittest.mock as mock
@ -94,3 +96,20 @@ def test_http_header_encoding():
mocked_socket.sendall(util.to_bytestring(header_str,"ascii")) mocked_socket.sendall(util.to_bytestring(header_str,"ascii"))
except Exception as e: except Exception as e:
assert isinstance(e, UnicodeEncodeError) assert isinstance(e, UnicodeEncodeError)
def test_http_inalid_response_header():
""" tests whether http response headers are contains control chars """
mocked_socket = mock.MagicMock()
mocked_socket.sendall = mock.MagicMock()
mocked_request = mock.MagicMock()
response = Response(mocked_request, mocked_socket, None)
with pytest.raises(InvalidHeader):
response.start_response("200 OK", [('foo', 'essai\r\n')])
response = Response(mocked_request, mocked_socket, None)
with pytest.raises(InvalidHeaderName):
response.start_response("200 OK", [('foo\r\n', 'essai')])