@@ -149,3 +149,33 @@ def test_conversion_edge_cases(self, filter_dict, expected):
149149 def test_invalid_filter_raises (self , filter_dict ):
150150 with pytest .raises (ValueError ):
151151 _convert_filters (filter_dict )
152+
153+ @pytest .mark .parametrize (
154+ "field" ,
155+ [
156+ "x; DROP TABLE Documents" ,
157+ "x OR 1=1" ,
158+ "x--" ,
159+ "x; SELECT *" ,
160+ "'injected'" ,
161+ "1field" ,
162+ "field name" ,
163+ ],
164+ )
165+ def test_sql_injection_field_names_raise (self , field ):
166+ with pytest .raises (ValueError , match = "Invalid field name" ):
167+ _convert_filters ({"field" : field , "operator" : "==" , "value" : "v" })
168+
169+ def test_value_with_backslash (self ):
170+ # A single backslash must be doubled: \ → \\
171+ result = _convert_filters ({"field" : "meta.x" , "operator" : "==" , "value" : "\\ " })
172+ assert result == "meta.x = '\\ \\ '"
173+
174+ def test_value_with_backslash_then_quote (self ):
175+ # \' in value → \\ (escaped backslash) + \' (escaped quote) in SQL
176+ result = _convert_filters ({"field" : "meta.x" , "operator" : "==" , "value" : "a\\ 'b" })
177+ assert result == "meta.x = 'a\\ \\ \\ 'b'"
178+
179+ def test_value_with_single_quote (self ):
180+ result = _convert_filters ({"field" : "meta.x" , "operator" : "==" , "value" : "it's" })
181+ assert result == "meta.x = 'it\\ 's'"
0 commit comments