From 840e7991cee136f4f194d4763a1a0564f499b7c0 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Fri, 23 May 2025 21:46:19 +0530 Subject: [PATCH] fix: dont allow partial backticks - add tests --- frappe/database/query.py | 7 ++----- frappe/tests/test_query.py | 12 ++++++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/frappe/database/query.py b/frappe/database/query.py index a7aa869db6..1418a681e8 100644 --- a/frappe/database/query.py +++ b/frappe/database/query.py @@ -29,12 +29,12 @@ TABLE_NAME_PATTERN = re.compile(r"^[\w -]*$", flags=re.ASCII) # Pattern to validate field names in SELECT: # Allows: name, `name`, name as alias, `name` as alias, `table name`.`name`, `table name`.`name` as alias, table.name, table.name as alias -ALLOWED_FIELD_PATTERN = re.compile(r"^(?:`?[\w\s-]+`?\.)?(`?\w+`?|\w+)(?:\s+as\s+\w+)?$", flags=re.ASCII) +ALLOWED_FIELD_PATTERN = re.compile(r"^(?:(`[\w\s-]+`|\w+)\.)?(`\w+`|\w+)(?:\s+as\s+\w+)?$", flags=re.ASCII) # Pattern to validate field names used in various SQL clauses (WHERE, GROUP BY, ORDER BY): # Allows simple field names, backticked names, and table-qualified names (e.g., name, `name`, `table`.`name`, table.name) # Does NOT allow aliases ('as alias') or functions. -ALLOWED_SQL_FIELD_PATTERN = re.compile(r"^(?:`?\w+`?\.)?(`?\w+`?|\w+)$", flags=re.ASCII) +ALLOWED_SQL_FIELD_PATTERN = re.compile(r"^(?:(`\w+`|\w+)\.)?(`\w+`|\w+)$", flags=re.ASCII) # Regex to parse field names: # Group 1: Optional quote for table name @@ -1331,6 +1331,3 @@ class CombinedRawCriterion(RawCriterion): left_sql = self.left.get_sql(**kwargs) if hasattr(self.left, "get_sql") else str(self.left) right_sql = self.right.get_sql(**kwargs) if hasattr(self.right, "get_sql") else str(self.right) return f"({left_sql}) {self.operator} ({right_sql})" - left_sql = self.left.get_sql(**kwargs) if hasattr(self.left, "get_sql") else str(self.left) - right_sql = self.right.get_sql(**kwargs) if hasattr(self.right, "get_sql") else str(self.right) - return f"({left_sql}) {self.operator} ({right_sql})" diff --git a/frappe/tests/test_query.py b/frappe/tests/test_query.py index fd5b2fea11..d26a95bde9 100644 --- a/frappe/tests/test_query.py +++ b/frappe/tests/test_query.py @@ -150,6 +150,7 @@ class TestQuery(IntegrationTestCase): "tabUser.name as alias", "`tabUser`.`name` as alias", "*", + "`tabHas Role`.`name`", ] invalid_fields = [ "name; DROP TABLE users", @@ -169,6 +170,12 @@ class TestQuery(IntegrationTestCase): "SUM(amount) as total", "COUNT(name) as alias; SELECT 1", "COUNT(name;)", + "`name", + "name`", + "`tabUser.name`", + "tabUser.`name", + "tabUser`.`name`", + "tab`User.name", ] for field in valid_fields: @@ -208,6 +215,11 @@ class TestQuery(IntegrationTestCase): "`table`.`invalid-field`", "field with space", "`field with space`", + "`name`", + "`name", + "name`", + "tabUser.`name`", + "`tabUser.name`", ] for field in valid_fields: