mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	widgets: Add range checks on backend for indexes.
This commit is contained in:
		@@ -141,6 +141,19 @@ def check_int_in(possible_values: List[int]) -> Validator[int]:
 | 
				
			|||||||
    return validator
 | 
					    return validator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def check_int_range(low: int, high: int) -> Validator[int]:
 | 
				
			||||||
 | 
					    # low and high are both treated as valid values
 | 
				
			||||||
 | 
					    def validator(var_name: str, val: object) -> int:
 | 
				
			||||||
 | 
					        n = check_int(var_name, val)
 | 
				
			||||||
 | 
					        if n < low:
 | 
				
			||||||
 | 
					            raise ValidationError(_("{var_name} is too small").format(var_name=var_name))
 | 
				
			||||||
 | 
					        if n > high:
 | 
				
			||||||
 | 
					            raise ValidationError(_("{var_name} is too large").format(var_name=var_name))
 | 
				
			||||||
 | 
					        return n
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return validator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def check_float(var_name: str, val: object) -> float:
 | 
					def check_float(var_name: str, val: object) -> float:
 | 
				
			||||||
    if not isinstance(val, float):
 | 
					    if not isinstance(val, float):
 | 
				
			||||||
        raise ValidationError(_("{var_name} is not a float").format(var_name=var_name))
 | 
					        raise ValidationError(_("{var_name} is not a float").format(var_name=var_name))
 | 
				
			||||||
@@ -455,6 +468,10 @@ def check_widget_content(widget_content: object) -> Dict[str, Any]:
 | 
				
			|||||||
    raise ValidationError("unknown widget type: " + widget_type)
 | 
					    raise ValidationError("unknown widget type: " + widget_type)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# This should match MAX_IDX in our client widgets. It is somewhat arbitrary.
 | 
				
			||||||
 | 
					MAX_IDX = 1000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def validate_poll_data(poll_data: object, is_widget_author: bool) -> None:
 | 
					def validate_poll_data(poll_data: object, is_widget_author: bool) -> None:
 | 
				
			||||||
    check_dict([("type", check_string)])("poll data", poll_data)
 | 
					    check_dict([("type", check_string)])("poll data", poll_data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -489,7 +506,7 @@ def validate_poll_data(poll_data: object, is_widget_author: bool) -> None:
 | 
				
			|||||||
            [
 | 
					            [
 | 
				
			||||||
                ("type", check_string),
 | 
					                ("type", check_string),
 | 
				
			||||||
                ("option", check_string),
 | 
					                ("option", check_string),
 | 
				
			||||||
                ("idx", check_int),
 | 
					                ("idx", check_int_range(0, MAX_IDX)),
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        checker("poll data", poll_data)
 | 
					        checker("poll data", poll_data)
 | 
				
			||||||
@@ -507,7 +524,7 @@ def validate_todo_data(todo_data: object) -> None:
 | 
				
			|||||||
        checker = check_dict_only(
 | 
					        checker = check_dict_only(
 | 
				
			||||||
            [
 | 
					            [
 | 
				
			||||||
                ("type", check_string),
 | 
					                ("type", check_string),
 | 
				
			||||||
                ("key", check_int),
 | 
					                ("key", check_int_range(0, MAX_IDX)),
 | 
				
			||||||
                ("task", check_string),
 | 
					                ("task", check_string),
 | 
				
			||||||
                ("desc", check_string),
 | 
					                ("desc", check_string),
 | 
				
			||||||
                ("completed", check_bool),
 | 
					                ("completed", check_bool),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -297,6 +297,8 @@ class WidgetContentTestCase(ZulipTestCase):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        assert_error('{"type": "new_option"}', "key is missing")
 | 
					        assert_error('{"type": "new_option"}', "key is missing")
 | 
				
			||||||
        assert_error('{"type": "new_option", "idx": 7, "option": 999}', "not a string")
 | 
					        assert_error('{"type": "new_option", "idx": 7, "option": 999}', "not a string")
 | 
				
			||||||
 | 
					        assert_error('{"type": "new_option", "idx": -1, "option": "pizza"}', "too small")
 | 
				
			||||||
 | 
					        assert_error('{"type": "new_option", "idx": 1001, "option": "pizza"}', "too large")
 | 
				
			||||||
        assert_error('{"type": "new_option", "idx": "bogus", "option": "maybe"}', "not an int")
 | 
					        assert_error('{"type": "new_option", "idx": "bogus", "option": "maybe"}', "not an int")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def assert_success(data: Dict[str, object]) -> None:
 | 
					        def assert_success(data: Dict[str, object]) -> None:
 | 
				
			||||||
@@ -348,6 +350,14 @@ class WidgetContentTestCase(ZulipTestCase):
 | 
				
			|||||||
            '{"type": "new_task", "key": 7, "task": 7, "desc": "", "completed": false}',
 | 
					            '{"type": "new_task", "key": 7, "task": 7, "desc": "", "completed": false}',
 | 
				
			||||||
            'data["task"] is not a string',
 | 
					            'data["task"] is not a string',
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					        assert_error(
 | 
				
			||||||
 | 
					            '{"type": "new_task", "key": -1, "task": "eat", "desc": "", "completed": false}',
 | 
				
			||||||
 | 
					            'data["key"] is too small',
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        assert_error(
 | 
				
			||||||
 | 
					            '{"type": "new_task", "key": 1001, "task": "eat", "desc": "", "completed": false}',
 | 
				
			||||||
 | 
					            'data["key"] is too large',
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert_error('{"type": "strike"}', "key is missing")
 | 
					        assert_error('{"type": "strike"}', "key is missing")
 | 
				
			||||||
        assert_error('{"type": "strike", "key": 999}', 'data["key"] is not a string')
 | 
					        assert_error('{"type": "strike", "key": 999}', 'data["key"] is not a string')
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user