#34459: SearchVector() can return query strings that are unsafe to combine.
----------------------------------+------------------------------------
Reporter: Patryk Zawadzki | Owner: (none)
Type: Bug | Status: new
Component: contrib.postgres | Version: 4.2
Severity: Release blocker | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
----------------------------------+------------------------------------
Comment (by Mariusz Felisiak):
We use `compose_sql()` in different places. Unfortunately, it's sometimes
used together with uncomposed SQL statements causing issues when binding
parameters. IMO, we should escape `%` when we know that the parameters are
bound later, e.g.
{{{#!diff
diff --git a/django/contrib/postgres/search.py
b/django/contrib/postgres/search.py
index 4e370aa167..279a39e80e 100644
--- a/django/contrib/postgres/search.py
+++ b/django/contrib/postgres/search.py
@@ -146,7 +146,9 @@ class SearchVector(SearchVectorCombinable, Func):
# These parameters must be bound on the client side because we
may
# want to create an index on this expression.
- sql = connection.ops.compose_sql(sql, config_params + params +
extra_params)
+ sql = connection.ops.compose_sql(
+ sql, config_params + params + extra_params, quote_params=True
+ )
return sql, []
@@ -321,7 +323,9 @@ class SearchHeadline(Func):
if self.options:
options_params.append(
", ".join(
- connection.ops.compose_sql(f"{option}=%s", [value])
+ connection.ops.compose_sql(
+ f"{option}=%s", [value], quote_params=True
+ )
for option, value in self.options.items()
)
)
diff --git a/django/db/backends/postgresql/operations.py
b/django/db/backends/postgresql/operations.py
index 18cfcb29cb..8aa8bb5173 100644
--- a/django/db/backends/postgresql/operations.py
+++ b/django/db/backends/postgresql/operations.py
@@ -201,7 +201,14 @@ class DatabaseOperations(BaseDatabaseOperations):
return name # Quoting once is enough.
return '"%s"' % name
- def compose_sql(self, sql, params):
+ def quote_value(self, value):
+ if isinstance(value, str):
+ value = value.replace("%", "%%")
+ return value
+
+ def compose_sql(self, sql, params, quote_params=False):
+ if quote_params and params:
+ params = [self.quote_value(param) for param in params]
return mogrify(sql, params, self.connection)
def set_time_zone_sql(self):
}}}
Patryk, does it work for you?
--
Ticket URL: <https://code.djangoproject.com/ticket/34459#comment:5>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/010701875068b052-09c0a72d-2ea6-498c-bfe3-6e3165b1b91a-000000%40eu-central-1.amazonses.com.