From 6029ccd44e500bd1d3ba41821793216cb4eac6dd Mon Sep 17 00:00:00 2001 From: Kevin_Zheng Date: Tue, 30 Jan 2018 17:28:01 +0800 Subject: [PATCH] Invalid query parameter could lead to HTTP 500 Invalid query parameter could lead to HTTP 500, although Nova used JSON Schema verification to check input query params, but query like: GET /servers?limit=%88 will still lead to HTTP 500, as it failed to parse at webob which is pre JSON Schema check. Partial-Bug: #1746202 Change-Id: I11b94a1aaeb67dc1a5abdcf0af5961ee8942a50a --- nova/api/validation/__init__.py | 13 ++++++++++++- nova/tests/unit/test_api_validation.py | 7 +++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/nova/api/validation/__init__.py b/nova/api/validation/__init__.py index 490c4ea870ee..6f1d0b3475e7 100644 --- a/nova/api/validation/__init__.py +++ b/nova/api/validation/__init__.py @@ -21,6 +21,8 @@ import re from nova.api.openstack import api_version_request as api_version from nova.api.validation import validators +from nova import exception +from nova.i18n import _ def _schema_validation_helper(schema, target, min_version, max_version, @@ -167,8 +169,17 @@ def query_schema(query_params_schema, min_version=None, else: req = args[1] + # NOTE(Kevin_Zheng): The webob package throws UnicodeError when + # param cannot be decoded. Catch this and raise HTTP 400. + + try: + query_dict = req.GET.dict_of_lists() + except UnicodeDecodeError: + msg = _('Query string is not UTF-8 encoded') + raise exception.ValidationError(msg) + if _schema_validation_helper(query_params_schema, - req.GET.dict_of_lists(), + query_dict, min_version, max_version, args, kwargs, is_body=False): # NOTE(alex_xu): The additional query parameters were stripped diff --git a/nova/tests/unit/test_api_validation.py b/nova/tests/unit/test_api_validation.py index 416ef62dcbad..9e3312153415 100644 --- a/nova/tests/unit/test_api_validation.py +++ b/nova/tests/unit/test_api_validation.py @@ -305,6 +305,13 @@ class QueryParamsSchemaTestCase(test.NoDBTestCase): req.api_version_request = api_version.APIVersionRequest("2.3") self.assertRaises(exception.ValidationError, self.controller.get, req) + def test_validate_request_unicode_decode_failure(self): + req = fakes.HTTPRequest.blank("/tests?foo=%88") + req.api_version_request = api_version.APIVersionRequest("2.1") + ex = self.assertRaises( + exception.ValidationError, self.controller.get, req) + self.assertIn("Query string is not UTF-8 encoded", six.text_type(ex)) + def test_strip_out_additional_properties(self): req = fakes.HTTPRequest.blank( "/tests?foos=abc&foo=%s&bar=123&-bar=456" % fakes.FAKE_UUID)