mirror of
https://github.com/django/django.git
synced 2025-06-21 11:29:12 +00:00
Fixed #36152 -- Deprecated use of "%" in column aliases.
Unintentional support existed only on SQLite and Oracle.
This commit is contained in:
parent
56f468681a
commit
8ede411a81
@ -10,7 +10,9 @@ all about the internals of models in order to get the information it needs.
|
|||||||
import copy
|
import copy
|
||||||
import difflib
|
import difflib
|
||||||
import functools
|
import functools
|
||||||
|
import inspect
|
||||||
import sys
|
import sys
|
||||||
|
import warnings
|
||||||
from collections import Counter, namedtuple
|
from collections import Counter, namedtuple
|
||||||
from collections.abc import Iterator, Mapping
|
from collections.abc import Iterator, Mapping
|
||||||
from itertools import chain, count, product
|
from itertools import chain, count, product
|
||||||
@ -42,12 +44,17 @@ from django.db.models.query_utils import (
|
|||||||
from django.db.models.sql.constants import INNER, LOUTER, ORDER_DIR, SINGLE
|
from django.db.models.sql.constants import INNER, LOUTER, ORDER_DIR, SINGLE
|
||||||
from django.db.models.sql.datastructures import BaseTable, Empty, Join, MultiJoin
|
from django.db.models.sql.datastructures import BaseTable, Empty, Join, MultiJoin
|
||||||
from django.db.models.sql.where import AND, OR, ExtraWhere, NothingNode, WhereNode
|
from django.db.models.sql.where import AND, OR, ExtraWhere, NothingNode, WhereNode
|
||||||
|
from django.utils.deprecation import RemovedInDjango70Warning
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.regex_helper import _lazy_re_compile
|
from django.utils.regex_helper import _lazy_re_compile
|
||||||
from django.utils.tree import Node
|
from django.utils.tree import Node
|
||||||
|
|
||||||
__all__ = ["Query", "RawQuery"]
|
__all__ = ["Query", "RawQuery"]
|
||||||
|
|
||||||
|
# RemovedInDjango70Warning: When the deprecation ends, replace with:
|
||||||
|
# Quotation marks ('"`[]), whitespace characters, semicolons, percent signs
|
||||||
|
# or inline SQL comments are forbidden in column aliases.
|
||||||
|
# FORBIDDEN_ALIAS_PATTERN = _lazy_re_compile(r"['`\"\]\[;\s]|%|--|/\*|\*/")
|
||||||
# Quotation marks ('"`[]), whitespace characters, semicolons, or inline
|
# Quotation marks ('"`[]), whitespace characters, semicolons, or inline
|
||||||
# SQL comments are forbidden in column aliases.
|
# SQL comments are forbidden in column aliases.
|
||||||
FORBIDDEN_ALIAS_PATTERN = _lazy_re_compile(r"['`\"\]\[;\s]|--|/\*|\*/")
|
FORBIDDEN_ALIAS_PATTERN = _lazy_re_compile(r"['`\"\]\[;\s]|--|/\*|\*/")
|
||||||
@ -1206,9 +1213,23 @@ class Query(BaseExpression):
|
|||||||
return alias or seen[None]
|
return alias or seen[None]
|
||||||
|
|
||||||
def check_alias(self, alias):
|
def check_alias(self, alias):
|
||||||
|
# RemovedInDjango70Warning: When the deprecation ends, remove.
|
||||||
|
if "%" in alias:
|
||||||
|
if "aggregate" in {frame.function for frame in inspect.stack()}:
|
||||||
|
stacklevel = 5
|
||||||
|
else:
|
||||||
|
# annotate() and alias().
|
||||||
|
stacklevel = 6
|
||||||
|
warnings.warn(
|
||||||
|
"Using percent signs in a column alias is deprecated.",
|
||||||
|
stacklevel=stacklevel,
|
||||||
|
category=RemovedInDjango70Warning,
|
||||||
|
)
|
||||||
if FORBIDDEN_ALIAS_PATTERN.search(alias):
|
if FORBIDDEN_ALIAS_PATTERN.search(alias):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"Column aliases cannot contain whitespace characters, quotation marks, "
|
"Column aliases cannot contain whitespace characters, quotation marks, "
|
||||||
|
# RemovedInDjango70Warning: When the deprecation ends, replace with:
|
||||||
|
# "semicolons, percent signs, or SQL comments."
|
||||||
"semicolons, or SQL comments."
|
"semicolons, or SQL comments."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -28,6 +28,9 @@ details on these changes.
|
|||||||
|
|
||||||
* The ``URLIZE_ASSUME_HTTPS`` transitional setting will be removed.
|
* The ``URLIZE_ASSUME_HTTPS`` transitional setting will be removed.
|
||||||
|
|
||||||
|
* Using a percent sign in a column alias or annotation will raise
|
||||||
|
``ValueError``.
|
||||||
|
|
||||||
* Support for setting the ``ADMINS`` or ``MANAGERS`` settings to a list of
|
* Support for setting the ``ADMINS`` or ``MANAGERS`` settings to a list of
|
||||||
(name, address) tuples will be removed.
|
(name, address) tuples will be removed.
|
||||||
|
|
||||||
|
@ -375,6 +375,8 @@ Miscellaneous
|
|||||||
``per_page`` argument of :class:`django.core.paginator.Paginator` and
|
``per_page`` argument of :class:`django.core.paginator.Paginator` and
|
||||||
:class:`django.core.paginator.AsyncPaginator` is deprecated.
|
:class:`django.core.paginator.AsyncPaginator` is deprecated.
|
||||||
|
|
||||||
|
* Using a percent sign in a column alias or annotation is deprecated.
|
||||||
|
|
||||||
Features removed in 6.0
|
Features removed in 6.0
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@ from django.db.models.functions import (
|
|||||||
from django.db.models.sql.query import get_field_names_from_opts
|
from django.db.models.sql.query import get_field_names_from_opts
|
||||||
from django.test import TestCase, skipUnlessDBFeature
|
from django.test import TestCase, skipUnlessDBFeature
|
||||||
from django.test.utils import register_lookup
|
from django.test.utils import register_lookup
|
||||||
|
from django.utils.deprecation import RemovedInDjango70Warning
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
Author,
|
Author,
|
||||||
@ -1157,6 +1158,11 @@ class NonAggregateAnnotationTestCase(TestCase):
|
|||||||
|
|
||||||
def test_alias_sql_injection(self):
|
def test_alias_sql_injection(self):
|
||||||
crafted_alias = """injected_name" from "annotations_book"; --"""
|
crafted_alias = """injected_name" from "annotations_book"; --"""
|
||||||
|
# RemovedInDjango70Warning: When the deprecation ends, replace with:
|
||||||
|
# msg = (
|
||||||
|
# "Column aliases cannot contain whitespace characters, quotation marks, "
|
||||||
|
# "semicolons, percent signs, or SQL comments."
|
||||||
|
# )
|
||||||
msg = (
|
msg = (
|
||||||
"Column aliases cannot contain whitespace characters, quotation marks, "
|
"Column aliases cannot contain whitespace characters, quotation marks, "
|
||||||
"semicolons, or SQL comments."
|
"semicolons, or SQL comments."
|
||||||
@ -1176,10 +1182,17 @@ class NonAggregateAnnotationTestCase(TestCase):
|
|||||||
"ali/*as",
|
"ali/*as",
|
||||||
"alias*/",
|
"alias*/",
|
||||||
"alias;",
|
"alias;",
|
||||||
|
# RemovedInDjango70Warning: When the deprecation ends, add this case.
|
||||||
|
# "alias%",
|
||||||
# [] are used by MSSQL.
|
# [] are used by MSSQL.
|
||||||
"alias[",
|
"alias[",
|
||||||
"alias]",
|
"alias]",
|
||||||
]
|
]
|
||||||
|
# RemovedInDjango70Warning: When the deprecation ends, replace with:
|
||||||
|
# msg = (
|
||||||
|
# "Column aliases cannot contain whitespace characters, quotation marks, "
|
||||||
|
# "semicolons, percent signs, or SQL comments."
|
||||||
|
# )
|
||||||
msg = (
|
msg = (
|
||||||
"Column aliases cannot contain whitespace characters, quotation marks, "
|
"Column aliases cannot contain whitespace characters, quotation marks, "
|
||||||
"semicolons, or SQL comments."
|
"semicolons, or SQL comments."
|
||||||
@ -1189,6 +1202,11 @@ class NonAggregateAnnotationTestCase(TestCase):
|
|||||||
with self.assertRaisesMessage(ValueError, msg):
|
with self.assertRaisesMessage(ValueError, msg):
|
||||||
Book.objects.annotate(**{crafted_alias: Value(1)})
|
Book.objects.annotate(**{crafted_alias: Value(1)})
|
||||||
|
|
||||||
|
def test_alias_containing_percent_sign_deprecation(self):
|
||||||
|
msg = "Using percent signs in a column alias is deprecated."
|
||||||
|
with self.assertRaisesMessage(RemovedInDjango70Warning, msg):
|
||||||
|
Book.objects.annotate(**{"alias%": Value(1)})
|
||||||
|
|
||||||
@skipUnless(connection.vendor == "postgresql", "PostgreSQL tests")
|
@skipUnless(connection.vendor == "postgresql", "PostgreSQL tests")
|
||||||
@skipUnlessDBFeature("supports_json_field")
|
@skipUnlessDBFeature("supports_json_field")
|
||||||
def test_set_returning_functions(self):
|
def test_set_returning_functions(self):
|
||||||
@ -1476,6 +1494,11 @@ class AliasTests(TestCase):
|
|||||||
|
|
||||||
def test_alias_sql_injection(self):
|
def test_alias_sql_injection(self):
|
||||||
crafted_alias = """injected_name" from "annotations_book"; --"""
|
crafted_alias = """injected_name" from "annotations_book"; --"""
|
||||||
|
# RemovedInDjango70Warning: When the deprecation ends, replace with:
|
||||||
|
# msg = (
|
||||||
|
# "Column aliases cannot contain whitespace characters, quotation marks, "
|
||||||
|
# "semicolons, percent signs, or SQL comments."
|
||||||
|
# )
|
||||||
msg = (
|
msg = (
|
||||||
"Column aliases cannot contain whitespace characters, quotation marks, "
|
"Column aliases cannot contain whitespace characters, quotation marks, "
|
||||||
"semicolons, or SQL comments."
|
"semicolons, or SQL comments."
|
||||||
|
Loading…
x
Reference in New Issue
Block a user