Fix(uri): More robust when querystring contains malformed percent sign (%).
Parse malformed percent sign as a plain "%" like [Google Search](https://www.google.com/?q=%%20%25) and other sites have done.
This commit is contained in:
		@@ -178,9 +178,12 @@ if six.PY2:
 | 
			
		||||
        tokens = decoded_uri.split('%')
 | 
			
		||||
        decoded_uri = tokens[0]
 | 
			
		||||
        for token in tokens[1:]:
 | 
			
		||||
            char, byte = _HEX_TO_BYTE[token[:2]]
 | 
			
		||||
            decoded_uri += char + token[2:]
 | 
			
		||||
 | 
			
		||||
            token_partial = token[:2]
 | 
			
		||||
            if token_partial in _HEX_TO_BYTE:
 | 
			
		||||
                char, byte = _HEX_TO_BYTE[token_partial]
 | 
			
		||||
            else:
 | 
			
		||||
                char, byte = '%', 0
 | 
			
		||||
            decoded_uri += char + (token[2:] if byte else token)
 | 
			
		||||
            only_ascii = only_ascii and (byte <= 127)
 | 
			
		||||
 | 
			
		||||
        # PERF(kgriffs): Only spend the time to do this if there
 | 
			
		||||
@@ -235,7 +238,12 @@ else:
 | 
			
		||||
        tokens = decoded_uri.split(b'%')
 | 
			
		||||
        decoded_uri = tokens[0]
 | 
			
		||||
        for token in tokens[1:]:
 | 
			
		||||
            decoded_uri += _HEX_TO_BYTE[token[:2]] + token[2:]
 | 
			
		||||
            token_partial = token[:2]
 | 
			
		||||
            if token_partial in _HEX_TO_BYTE:
 | 
			
		||||
                decoded_uri += _HEX_TO_BYTE[token_partial] + token[2:]
 | 
			
		||||
            else:
 | 
			
		||||
                # malformed percentage like "x=%" or "y=%+"
 | 
			
		||||
                decoded_uri += b'%' + token
 | 
			
		||||
 | 
			
		||||
        # Convert back to str
 | 
			
		||||
        return decoded_uri.decode('utf-8', 'replace')
 | 
			
		||||
 
 | 
			
		||||
@@ -64,6 +64,16 @@ class _TestQueryParams(testing.TestBase):
 | 
			
		||||
        self.assertEqual(req.get_param_as_list('id', int), [23, 42])
 | 
			
		||||
        self.assertEqual(req.get_param('q'), u'\u8c46 \u74e3')
 | 
			
		||||
 | 
			
		||||
    def test_bad_percentage(self):
 | 
			
		||||
        query_string = 'x=%%20%+%&y=peregrine&z=%a%z%zz%1%20e'
 | 
			
		||||
        self.simulate_request('/', query_string=query_string)
 | 
			
		||||
        self.assertEqual(self.srmock.status, falcon.HTTP_200)
 | 
			
		||||
 | 
			
		||||
        req = self.resource.req
 | 
			
		||||
        self.assertEqual(req.get_param('x'), '% % %')
 | 
			
		||||
        self.assertEqual(req.get_param('y'), 'peregrine')
 | 
			
		||||
        self.assertEqual(req.get_param('z'), '%a%z%zz%1 e')
 | 
			
		||||
 | 
			
		||||
    def test_allowed_names(self):
 | 
			
		||||
        query_string = ('p=0&p1=23&2p=foo&some-thing=that&blank=&'
 | 
			
		||||
                        'some_thing=x&-bogus=foo&more.things=blah&'
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user