summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSenthil Kumaran <senthil@uthcode.com>2020-12-05 13:26:24 (GMT)
committerGitHub <noreply@github.com>2020-12-05 13:26:24 (GMT)
commitda3d2abe6be9fcf18cac12ec5d7d9f1180d94b5e (patch)
tree20e9e1dcf25c25fcfc998cae6f0b6f2049749edb
parent556d97f473fa538cef780f84bd29239ecf57d9c5 (diff)
downloadcpython-da3d2abe6be9fcf18cac12ec5d7d9f1180d94b5e.zip
cpython-da3d2abe6be9fcf18cac12ec5d7d9f1180d94b5e.tar.gz
cpython-da3d2abe6be9fcf18cac12ec5d7d9f1180d94b5e.tar.bz2
GH-5054: CGIHTTPRequestHandler.run_cgi() HTTP_ACCEPT improperly parsed (#23638)
-rw-r--r--Lib/http/server.py7
-rw-r--r--Lib/test/test_httpservers.py37
-rw-r--r--Misc/NEWS.d/next/Library/2020-12-04-03-51-12.bpo-5054.53StYZ.rst5
3 files changed, 41 insertions, 8 deletions
diff --git a/Lib/http/server.py b/Lib/http/server.py
index c611381..94f730e 100644
--- a/Lib/http/server.py
+++ b/Lib/http/server.py
@@ -1122,12 +1122,7 @@ class CGIHTTPRequestHandler(SimpleHTTPRequestHandler):
referer = self.headers.get('referer')
if referer:
env['HTTP_REFERER'] = referer
- accept = []
- for line in self.headers.getallmatchingheaders('accept'):
- if line[:1] in "\t\n\r ":
- accept.append(line.strip())
- else:
- accept = accept + line[7:].split(',')
+ accept = self.headers.get_all('accept', ())
env['HTTP_ACCEPT'] = ','.join(accept)
ua = self.headers.get('user-agent')
if ua:
diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py
index 2859abb..c3d7c8f 100644
--- a/Lib/test/test_httpservers.py
+++ b/Lib/test/test_httpservers.py
@@ -3,7 +3,7 @@
Written by Cody A.W. Somerville <cody-somerville@ubuntu.com>,
Josip Dzolonga, and Michael Otteneder for the 2007/08 GHOP contest.
"""
-
+from collections import OrderedDict
from http.server import BaseHTTPRequestHandler, HTTPServer, \
SimpleHTTPRequestHandler, CGIHTTPRequestHandler
from http import server, HTTPStatus
@@ -19,7 +19,7 @@ import shutil
import email.message
import email.utils
import html
-import http.client
+import http, http.client
import urllib.parse
import tempfile
import time
@@ -588,6 +588,15 @@ print()
print(os.environ["%s"])
"""
+cgi_file6 = """\
+#!%s
+import os
+
+print("Content-type: text/plain")
+print()
+print(repr(os.environ))
+"""
+
@unittest.skipIf(hasattr(os, 'geteuid') and os.geteuid() == 0,
"This test can't be run reliably as root (issue #13308).")
@@ -666,6 +675,11 @@ class CGIHTTPServerTestCase(BaseTestCase):
file5.write(cgi_file1 % self.pythonexe)
os.chmod(self.file5_path, 0o777)
+ self.file6_path = os.path.join(self.cgi_dir, 'file6.py')
+ with open(self.file6_path, 'w', encoding='utf-8') as file6:
+ file6.write(cgi_file6 % self.pythonexe)
+ os.chmod(self.file6_path, 0o777)
+
os.chdir(self.parent_dir)
def tearDown(self):
@@ -685,6 +699,8 @@ class CGIHTTPServerTestCase(BaseTestCase):
os.remove(self.file4_path)
if self.file5_path:
os.remove(self.file5_path)
+ if self.file6_path:
+ os.remove(self.file6_path)
os.rmdir(self.cgi_child_dir)
os.rmdir(self.cgi_dir)
os.rmdir(self.cgi_dir_in_sub_dir)
@@ -818,6 +834,23 @@ class CGIHTTPServerTestCase(BaseTestCase):
finally:
CGIHTTPRequestHandler.cgi_directories.remove('/sub/dir/cgi-bin')
+ def test_accept(self):
+ browser_accept = \
+ 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
+ tests = (
+ ((('Accept', browser_accept),), browser_accept),
+ ((), ''),
+ # Hack case to get two values for the one header
+ ((('Accept', 'text/html'), ('ACCEPT', 'text/plain')),
+ 'text/html,text/plain'),
+ )
+ for headers, expected in tests:
+ headers = OrderedDict(headers)
+ with self.subTest(headers):
+ res = self.request('/cgi-bin/file6.py', 'GET', headers=headers)
+ self.assertEqual(http.HTTPStatus.OK, res.status)
+ expected = f"'HTTP_ACCEPT': {expected!r}"
+ self.assertIn(expected.encode('ascii'), res.read())
class SocketlessRequestHandler(SimpleHTTPRequestHandler):
diff --git a/Misc/NEWS.d/next/Library/2020-12-04-03-51-12.bpo-5054.53StYZ.rst b/Misc/NEWS.d/next/Library/2020-12-04-03-51-12.bpo-5054.53StYZ.rst
new file mode 100644
index 0000000..ad8163c
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-12-04-03-51-12.bpo-5054.53StYZ.rst
@@ -0,0 +1,5 @@
+CGIHTTPRequestHandler.run_cgi() HTTP_ACCEPT improperly parsed. Replace the
+special purpose getallmatchingheaders with generic get_all method and add
+relevant tests.
+
+Original Patch by Martin Panter. Modified by Senthil Kumaran.