diff --git a/cherrypy/lib/httputil.py b/cherrypy/lib/httputil.py index 66ba01140..c00b75cf1 100644 --- a/cherrypy/lib/httputil.py +++ b/cherrypy/lib/httputil.py @@ -18,6 +18,7 @@ from six.moves import range, builtins from six.moves.BaseHTTPServer import BaseHTTPRequestHandler +import cherrypy from cherrypy._cpcompat import ntob, ntou from cherrypy._cpcompat import text_or_bytes from cherrypy._cpcompat import unquote_qs @@ -202,7 +203,21 @@ def qvalue(self): val = self.params.get('q', '1') if isinstance(val, HeaderElement): val = val.value - return float(val) + try: + return float(val) + except ValueError as val_err: + """Fail client requests with invalid quality value. + + Ref: https://github.com/cherrypy/cherrypy/issues/1370 + """ + six.raise_from( + cherrypy.HTTPError( + 400, + 'Malformed HTTP header: `{}`'. + format(str(self)), + ), + val_err, + ) def __cmp__(self, other): diff = builtins.cmp(self.qvalue, other.qvalue) diff --git a/cherrypy/test/test_encoding.py b/cherrypy/test/test_encoding.py index 97adad94a..ab24ab936 100644 --- a/cherrypy/test/test_encoding.py +++ b/cherrypy/test/test_encoding.py @@ -360,6 +360,11 @@ def testEncoding(self): self.getPage('/utf8', [('Accept-Charset', 'us-ascii, ISO-8859-1')]) self.assertStatus('406 Not Acceptable') + # Test malformed quality value, which should raise 400. + self.getPage('/mao_zedong', [('Accept-Charset', + 'ISO-8859-1,utf-8;q=0.7,*;q=0.7)')]) + self.assertStatus('400 Bad Request') + def testGzip(self): zbuf = io.BytesIO() zfile = gzip.GzipFile(mode='wb', fileobj=zbuf, compresslevel=9)