From 0e2193982ab1e4941ed82c3785e306eb8e4e46ec Mon Sep 17 00:00:00 2001 From: TommyLike Date: Wed, 31 Jan 2018 09:41:13 +0800 Subject: [PATCH] Fix UnicodeDecodeError when decode API input Convert UnicodeDecodeError to HTTPBadRequest in FaultWrapper. **NOTE**: Cinder will raise 500 error when failed to decode invalid unicode character at anyplace where try to collect url parematers as below: ``` params = req.params ``` This patch converts this kind of exception into BadRequest, plus an explicit error message. Change-Id: I816f05084b0a0ef670ef293d381868409b96ed7d Closes-Bug: #1746202 --- cinder/api/middleware/fault.py | 5 +++++ cinder/tests/unit/api/middleware/test_faults.py | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/cinder/api/middleware/fault.py b/cinder/api/middleware/fault.py index e25de79569b..e170b4c4633 100644 --- a/cinder/api/middleware/fault.py +++ b/cinder/api/middleware/fault.py @@ -44,6 +44,11 @@ class FaultWrapper(base_wsgi.Middleware): status, webob.exc.HTTPInternalServerError)() def _error(self, inner, req): + if isinstance(inner, UnicodeDecodeError): + msg = _("Error decoding your request. Either the URL or the " + "request body contained characters that could not be " + "decoded by Cinder.") + return wsgi.Fault(webob.exc.HTTPBadRequest(explanation=msg)) if not isinstance(inner, exception.QuotaError): LOG.exception("Caught error: %(type)s %(error)s", {'type': type(inner), diff --git a/cinder/tests/unit/api/middleware/test_faults.py b/cinder/tests/unit/api/middleware/test_faults.py index a284b78548d..e9531191273 100644 --- a/cinder/tests/unit/api/middleware/test_faults.py +++ b/cinder/tests/unit/api/middleware/test_faults.py @@ -17,6 +17,7 @@ from oslo_serialization import jsonutils from six.moves import http_client import webob.dec +from cinder.api.middleware import fault from cinder.api.openstack import wsgi from cinder import test @@ -79,3 +80,18 @@ class TestFaults(test.TestCase): """Ensure the status_int is set correctly on faults.""" fault = wsgi.Fault(webob.exc.HTTPBadRequest(explanation='what?')) self.assertEqual(http_client.BAD_REQUEST, fault.status_int) + + +class ExceptionTest(test.TestCase): + + def _wsgi_app(self, inner_app): + return fault.FaultWrapper(inner_app) + + def test_unicode_decode_error(self): + @webob.dec.wsgify + def unicode_error(req): + raise UnicodeDecodeError("ascii", b"", 0, 1, "bad") + + api = self._wsgi_app(unicode_error) + resp = webob.Request.blank('/').get_response(api) + self.assertEqual(400, resp.status_int)