From 7d59c6d37c3b675b85d218f733ed24ca006a9d05 Mon Sep 17 00:00:00 2001
From: Mariusz Felisiak <felisiak.mariusz@gmail.com>
Date: Sat, 9 Jul 2022 13:02:07 +0200
Subject: [PATCH] [4.1.x] Refs CVE-2022-34265 -- Unified
 DatabaseOperations._convert_*_to_tz() hook names.

Backport of 5e2f4ddf2940704a26a4ac782b851989668d74db from main
---
 django/db/backends/mysql/operations.py  | 14 +++++++-------
 django/db/backends/oracle/operations.py | 14 +++++++-------
 docs/releases/4.1.txt                   |  4 ++++
 3 files changed, 18 insertions(+), 14 deletions(-)

diff --git a/django/db/backends/mysql/operations.py b/django/db/backends/mysql/operations.py
index 10cec41b61..8a875a11d8 100644
--- a/django/db/backends/mysql/operations.py
+++ b/django/db/backends/mysql/operations.py
@@ -66,7 +66,7 @@ class DatabaseOperations(BaseDatabaseOperations):
             return f"EXTRACT({lookup_type} FROM {sql})", params
 
     def date_trunc_sql(self, lookup_type, sql, params, tzname=None):
-        sql, params = self._convert_field_to_tz(sql, params, tzname)
+        sql, params = self._convert_sql_to_tz(sql, params, tzname)
         fields = {
             "year": "%Y-01-01",
             "month": "%Y-%m-01",
@@ -89,7 +89,7 @@ class DatabaseOperations(BaseDatabaseOperations):
         tzname, sign, offset = split_tzname_delta(tzname)
         return f"{sign}{offset}" if offset else tzname
 
-    def _convert_field_to_tz(self, sql, params, tzname):
+    def _convert_sql_to_tz(self, sql, params, tzname):
         if tzname and settings.USE_TZ and self.connection.timezone_name != tzname:
             return f"CONVERT_TZ({sql}, %s, %s)", (
                 *params,
@@ -99,19 +99,19 @@ class DatabaseOperations(BaseDatabaseOperations):
         return sql, params
 
     def datetime_cast_date_sql(self, sql, params, tzname):
-        sql, params = self._convert_field_to_tz(sql, params, tzname)
+        sql, params = self._convert_sql_to_tz(sql, params, tzname)
         return f"DATE({sql})", params
 
     def datetime_cast_time_sql(self, sql, params, tzname):
-        sql, params = self._convert_field_to_tz(sql, params, tzname)
+        sql, params = self._convert_sql_to_tz(sql, params, tzname)
         return f"TIME({sql})", params
 
     def datetime_extract_sql(self, lookup_type, sql, params, tzname):
-        sql, params = self._convert_field_to_tz(sql, params, tzname)
+        sql, params = self._convert_sql_to_tz(sql, params, tzname)
         return self.date_extract_sql(lookup_type, sql, params)
 
     def datetime_trunc_sql(self, lookup_type, sql, params, tzname):
-        sql, params = self._convert_field_to_tz(sql, params, tzname)
+        sql, params = self._convert_sql_to_tz(sql, params, tzname)
         fields = ["year", "month", "day", "hour", "minute", "second"]
         format = ("%Y-", "%m", "-%d", " %H:", "%i", ":%s")
         format_def = ("0000-", "01", "-01", " 00:", "00", ":00")
@@ -136,7 +136,7 @@ class DatabaseOperations(BaseDatabaseOperations):
         return sql, params
 
     def time_trunc_sql(self, lookup_type, sql, params, tzname=None):
-        sql, params = self._convert_field_to_tz(sql, params, tzname)
+        sql, params = self._convert_sql_to_tz(sql, params, tzname)
         fields = {
             "hour": "%H:00:00",
             "minute": "%H:%i:00",
diff --git a/django/db/backends/oracle/operations.py b/django/db/backends/oracle/operations.py
index 55c87ae84d..351de4df83 100644
--- a/django/db/backends/oracle/operations.py
+++ b/django/db/backends/oracle/operations.py
@@ -105,7 +105,7 @@ END;
         return extract_sql, (*params, extract_param)
 
     def date_trunc_sql(self, lookup_type, sql, params, tzname=None):
-        sql, params = self._convert_field_to_tz(sql, params, tzname)
+        sql, params = self._convert_sql_to_tz(sql, params, tzname)
         # https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/ROUND-and-TRUNC-Date-Functions.html
         trunc_param = None
         if lookup_type in ("year", "month"):
@@ -128,7 +128,7 @@ END;
         tzname, sign, offset = split_tzname_delta(tzname)
         return f"{sign}{offset}" if offset else tzname
 
-    def _convert_field_to_tz(self, sql, params, tzname):
+    def _convert_sql_to_tz(self, sql, params, tzname):
         if not (settings.USE_TZ and tzname):
             return sql, params
         if not self._tzname_re.match(tzname):
@@ -147,13 +147,13 @@ END;
         return sql, params
 
     def datetime_cast_date_sql(self, sql, params, tzname):
-        sql, params = self._convert_field_to_tz(sql, params, tzname)
+        sql, params = self._convert_sql_to_tz(sql, params, tzname)
         return f"TRUNC({sql})", params
 
     def datetime_cast_time_sql(self, sql, params, tzname):
         # Since `TimeField` values are stored as TIMESTAMP change to the
         # default date and convert the field to the specified timezone.
-        sql, params = self._convert_field_to_tz(sql, params, tzname)
+        sql, params = self._convert_sql_to_tz(sql, params, tzname)
         convert_datetime_sql = (
             f"TO_TIMESTAMP(CONCAT('1900-01-01 ', TO_CHAR({sql}, 'HH24:MI:SS.FF')), "
             f"'YYYY-MM-DD HH24:MI:SS.FF')"
@@ -164,11 +164,11 @@ END;
         )
 
     def datetime_extract_sql(self, lookup_type, sql, params, tzname):
-        sql, params = self._convert_field_to_tz(sql, params, tzname)
+        sql, params = self._convert_sql_to_tz(sql, params, tzname)
         return self.date_extract_sql(lookup_type, sql, params)
 
     def datetime_trunc_sql(self, lookup_type, sql, params, tzname):
-        sql, params = self._convert_field_to_tz(sql, params, tzname)
+        sql, params = self._convert_sql_to_tz(sql, params, tzname)
         # https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/ROUND-and-TRUNC-Date-Functions.html
         trunc_param = None
         if lookup_type in ("year", "month"):
@@ -192,7 +192,7 @@ END;
         # The implementation is similar to `datetime_trunc_sql` as both
         # `DateTimeField` and `TimeField` are stored as TIMESTAMP where
         # the date part of the later is ignored.
-        sql, params = self._convert_field_to_tz(sql, params, tzname)
+        sql, params = self._convert_sql_to_tz(sql, params, tzname)
         trunc_param = None
         if lookup_type == "hour":
             trunc_param = "HH24"
diff --git a/docs/releases/4.1.txt b/docs/releases/4.1.txt
index 49bbf2dec2..e8cd11349b 100644
--- a/docs/releases/4.1.txt
+++ b/docs/releases/4.1.txt
@@ -459,6 +459,10 @@ backends.
   ``DatabaseOperations.insert_statement()`` method is replaced by
   ``on_conflict`` that accepts ``django.db.models.constants.OnConflict``.
 
+* ``DatabaseOperations._convert_field_to_tz()`` is replaced by
+  ``DatabaseOperations._convert_sql_to_tz()`` that accepts the ``sql``,
+  ``params``, and ``tzname`` arguments.
+
 * Several date and time methods on ``DatabaseOperations`` now take ``sql`` and
   ``params`` arguments instead of ``field_name`` and return 2-tuple containing
   some SQL and the parameters to be interpolated into that SQL. The changed