From 897156aa536de6c10d9b20f6f96eb90f4fc9f473 Mon Sep 17 00:00:00 2001 From: Senthil Kumaran Date: Wed, 2 Dec 2020 20:55:01 -0800 Subject: [PATCH 1/3] CGI Accept Header Patch. --- Lib/http/server.py | 7 +------ Lib/test/test_httpservers.py | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/Lib/http/server.py b/Lib/http/server.py index ee991821099135..19dfd74c6c6275 100644 --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -1123,12 +1123,7 @@ def run_cgi(self): 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 2859abb21fc9f5..d81071b63ae709 100644 --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -3,7 +3,7 @@ Written by Cody A.W. Somerville , 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 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 @@ def test_html_escape_filename(self): print(os.environ["%s"]) """ +cgi_env = """\ +#!%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 @@ def setUp(self): file5.write(cgi_file1 % self.pythonexe) os.chmod(self.file5_path, 0o777) + self.env_path = os.path.join(self.cgi_dir, 'env.py') + with open(self.env_path, 'w', encoding='utf-8') as envfile: + envfile.write(cgi_env % self.pythonexe) + os.chmod(self.env_path, 0o777) + os.chdir(self.parent_dir) def tearDown(self): @@ -818,6 +832,23 @@ def test_cgi_path_in_sub_directories(self): 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/env.py', 'GET', headers=headers) + self.assertEqual(http.HTTPStatus.OK, res.status) + expected = r"'HTTP_ACCEPT': " + repr(expected) + self.assertIn(expected.encode('ascii'), res.read()) class SocketlessRequestHandler(SimpleHTTPRequestHandler): From 78dd084d367a41f92fb778f85ed03b88bc39b7a0 Mon Sep 17 00:00:00 2001 From: Senthil Kumaran Date: Thu, 3 Dec 2020 05:14:41 -0800 Subject: [PATCH 2/3] Update HTTP Servers. --- Lib/test/test_httpservers.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py index d81071b63ae709..c3d7c8feb1ec0d 100644 --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -588,7 +588,7 @@ def test_html_escape_filename(self): print(os.environ["%s"]) """ -cgi_env = """\ +cgi_file6 = """\ #!%s import os @@ -675,10 +675,10 @@ def setUp(self): file5.write(cgi_file1 % self.pythonexe) os.chmod(self.file5_path, 0o777) - self.env_path = os.path.join(self.cgi_dir, 'env.py') - with open(self.env_path, 'w', encoding='utf-8') as envfile: - envfile.write(cgi_env % self.pythonexe) - os.chmod(self.env_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) @@ -699,6 +699,8 @@ def tearDown(self): 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) @@ -845,9 +847,9 @@ def test_accept(self): for headers, expected in tests: headers = OrderedDict(headers) with self.subTest(headers): - res = self.request('/cgi-bin/env.py', 'GET', headers=headers) + res = self.request('/cgi-bin/file6.py', 'GET', headers=headers) self.assertEqual(http.HTTPStatus.OK, res.status) - expected = r"'HTTP_ACCEPT': " + repr(expected) + expected = f"'HTTP_ACCEPT': {expected!r}" self.assertIn(expected.encode('ascii'), res.read()) From 6cd1037242ecb59073fd4dcbb74f370c27c9ee99 Mon Sep 17 00:00:00 2001 From: Senthil Kumaran Date: Fri, 4 Dec 2020 03:52:44 -0800 Subject: [PATCH 3/3] Update News --- .../next/Library/2020-12-04-03-51-12.bpo-5054.53StYZ.rst | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2020-12-04-03-51-12.bpo-5054.53StYZ.rst 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 00000000000000..ad8163c7c1d206 --- /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.