sql: escape ILike/ElementILike value (#55528)

\, _ and % must be escaped.
This commit is contained in:
Benjamin Dauvergne 2021-07-12 16:01:32 +02:00
parent 8314648278
commit 549e513bf6
2 changed files with 51 additions and 2 deletions

View File

@ -516,3 +516,45 @@ def test_data_source_custom_view_digest(pub):
cards = CardDef.get_data_source_items('carddef:foo:view', get_by_text='Hello Foo Bar')
assert len(cards) == 1
assert cards[0]['text'] == 'Hello Foo Bar'
def test_data_source_query_escape(pub):
CardDef.wipe()
carddef = CardDef()
carddef.name = 'foo'
carddef.fields = [
StringField(id='1', label='Test', type='string', varname='foo'),
]
carddef.digest_templates = {'default': '{{ form_var_foo }}'}
carddef.store()
carddef.data_class().wipe()
carddata = carddef.data_class()()
carddata.data = {'1': 'Astreinte\\Lundi %'}
carddata.just_created()
carddata.store()
carddata2 = carddef.data_class()()
carddata2.data = {'1': 'Astreinte\\Mardi _'}
carddata2.just_created()
carddata2.store()
cards = CardDef.get_data_source_items('carddef:foo', query='astreinte')
assert len(cards) == 2
assert cards[0]['text'] == 'Astreinte\\Lundi %'
cards = CardDef.get_data_source_items('carddef:foo', query='astreinte\\')
assert len(cards) == 2
assert cards[0]['text'] == 'Astreinte\\Lundi %'
cards = CardDef.get_data_source_items('carddef:foo', query='astreinte\\l')
assert len(cards) == 1
assert cards[0]['text'] == 'Astreinte\\Lundi %'
cards = CardDef.get_data_source_items('carddef:foo', query='%')
assert len(cards) == 1
assert cards[0]['text'] == 'Astreinte\\Lundi %'
cards = CardDef.get_data_source_items('carddef:foo', query='_')
assert len(cards) == 1
assert cards[0]['text'] == 'Astreinte\\Mardi _'

View File

@ -87,6 +87,13 @@ SQL_TYPE_MAPPING = {
}
def like_escape(value):
value = value.replace('\\', '\\\\')
value = value.replace('_', '\\_')
value = value.replace('%', '\\%')
return value
def pickle_loads(value):
if hasattr(value, 'tobytes'):
value = value.tobytes()
@ -261,7 +268,7 @@ class Intersects(Criteria):
class ILike(Criteria):
def __init__(self, attribute, value, **kwargs):
super().__init__(attribute, value, **kwargs)
self.value = '%' + self.value + '%'
self.value = '%' + like_escape(self.value) + '%'
def as_sql(self):
return '%s ILIKE %%(c%s)s' % (self.attribute, id(self.value))
@ -291,7 +298,7 @@ class ElementEqual(Criteria):
class ElementILike(ElementEqual):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.value = '%' + self.value + '%'
self.value = '%' + like_escape(self.value) + '%'
def as_sql(self):
return "%s->>'%s' ILIKE %%(c%s)s" % (self.attribute, self.key, id(self.value))