mirror of
				https://github.com/django/django.git
				synced 2025-10-31 01:25:32 +00:00 
			
		
		
		
	[3.0.x] Fixed #30769 -- Fixed a crash when filtering against a subquery JSON/HStoreField annotation.
This was a regression introduced by7deeabc7c7to address CVE-2019-14234. Thanks Tim Kleinschmidt for the report and Mariusz for the tests. Backport of6c3dfba892from master
This commit is contained in:
		
				
					committed by
					
						 Mariusz Felisiak
						Mariusz Felisiak
					
				
			
			
				
	
			
			
			
						parent
						
							7bd28727ad
						
					
				
				
					commit
					574154ef56
				
			| @@ -86,7 +86,7 @@ class KeyTransform(Transform): | |||||||
|  |  | ||||||
|     def as_sql(self, compiler, connection): |     def as_sql(self, compiler, connection): | ||||||
|         lhs, params = compiler.compile(self.lhs) |         lhs, params = compiler.compile(self.lhs) | ||||||
|         return '(%s -> %%s)' % lhs, params + [self.key_name] |         return '(%s -> %%s)' % lhs, tuple(params) + (self.key_name,) | ||||||
|  |  | ||||||
|  |  | ||||||
| class KeyTransformFactory: | class KeyTransformFactory: | ||||||
|   | |||||||
| @@ -112,7 +112,7 @@ class KeyTransform(Transform): | |||||||
|             lookup = int(self.key_name) |             lookup = int(self.key_name) | ||||||
|         except ValueError: |         except ValueError: | ||||||
|             lookup = self.key_name |             lookup = self.key_name | ||||||
|         return '(%s %s %%s)' % (lhs, self.operator), params + [lookup] |         return '(%s %s %%s)' % (lhs, self.operator), tuple(params) + (lookup,) | ||||||
|  |  | ||||||
|  |  | ||||||
| class KeyTextTransform(KeyTransform): | class KeyTextTransform(KeyTransform): | ||||||
|   | |||||||
| @@ -9,4 +9,6 @@ Django 1.11.25 fixes a regression in 1.11.23. | |||||||
| Bugfixes | Bugfixes | ||||||
| ======== | ======== | ||||||
|  |  | ||||||
| * ... | * Fixed a crash when filtering with a ``Subquery()`` annotation of a queryset | ||||||
|  |   containing :class:`~django.contrib.postgres.fields.JSONField` or | ||||||
|  |   :class:`~django.contrib.postgres.fields.HStoreField` (:ticket:`30769`). | ||||||
|   | |||||||
| @@ -9,4 +9,6 @@ Django 2.1.13 fixes a regression in 2.1.11. | |||||||
| Bugfixes | Bugfixes | ||||||
| ======== | ======== | ||||||
|  |  | ||||||
| * ... | * Fixed a crash when filtering with a ``Subquery()`` annotation of a queryset | ||||||
|  |   containing :class:`~django.contrib.postgres.fields.JSONField` or | ||||||
|  |   :class:`~django.contrib.postgres.fields.HStoreField` (:ticket:`30769`). | ||||||
|   | |||||||
| @@ -11,3 +11,8 @@ Bugfixes | |||||||
|  |  | ||||||
| * Fixed migrations crash on SQLite when altering a model containing partial | * Fixed migrations crash on SQLite when altering a model containing partial | ||||||
|   indexes (:ticket:`30754`). |   indexes (:ticket:`30754`). | ||||||
|  |  | ||||||
|  | * Fixed a regression in Django 2.2.4 that caused a crash when filtering with a | ||||||
|  |   ``Subquery()`` annotation of a queryset containing | ||||||
|  |   :class:`~django.contrib.postgres.fields.JSONField` or | ||||||
|  |   :class:`~django.contrib.postgres.fields.HStoreField` (:ticket:`30769`). | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ import json | |||||||
|  |  | ||||||
| from django.core import checks, exceptions, serializers | from django.core import checks, exceptions, serializers | ||||||
| from django.db import connection | from django.db import connection | ||||||
| from django.db.models.expressions import RawSQL | from django.db.models.expressions import OuterRef, RawSQL, Subquery | ||||||
| from django.forms import Form | from django.forms import Form | ||||||
| from django.test.utils import CaptureQueriesContext, isolate_apps | from django.test.utils import CaptureQueriesContext, isolate_apps | ||||||
|  |  | ||||||
| @@ -207,6 +207,12 @@ class TestQuerying(PostgreSQLTestCase): | |||||||
|             queries[0]['sql'], |             queries[0]['sql'], | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|  |     def test_obj_subquery_lookup(self): | ||||||
|  |         qs = HStoreModel.objects.annotate( | ||||||
|  |             value=Subquery(HStoreModel.objects.filter(pk=OuterRef('pk')).values('field')), | ||||||
|  |         ).filter(value__a='b') | ||||||
|  |         self.assertSequenceEqual(qs, self.objs[:2]) | ||||||
|  |  | ||||||
|  |  | ||||||
| @isolate_apps('postgres_tests') | @isolate_apps('postgres_tests') | ||||||
| class TestChecks(PostgreSQLSimpleTestCase): | class TestChecks(PostgreSQLSimpleTestCase): | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ from decimal import Decimal | |||||||
| from django.core import checks, exceptions, serializers | from django.core import checks, exceptions, serializers | ||||||
| from django.core.serializers.json import DjangoJSONEncoder | from django.core.serializers.json import DjangoJSONEncoder | ||||||
| from django.db import connection | from django.db import connection | ||||||
| from django.db.models import Count, F, Q | from django.db.models import Count, F, OuterRef, Q, Subquery | ||||||
| from django.db.models.expressions import RawSQL | from django.db.models.expressions import RawSQL | ||||||
| from django.db.models.functions import Cast | from django.db.models.functions import Cast | ||||||
| from django.forms import CharField, Form, widgets | from django.forms import CharField, Form, widgets | ||||||
| @@ -303,6 +303,12 @@ class TestQuerying(PostgreSQLTestCase): | |||||||
|             [self.objs[7], self.objs[8]] |             [self.objs[7], self.objs[8]] | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|  |     def test_obj_subquery_lookup(self): | ||||||
|  |         qs = JSONModel.objects.annotate( | ||||||
|  |             value=Subquery(JSONModel.objects.filter(pk=OuterRef('pk')).values('field')), | ||||||
|  |         ).filter(value__a='b') | ||||||
|  |         self.assertSequenceEqual(qs, [self.objs[7], self.objs[8]]) | ||||||
|  |  | ||||||
|     def test_deep_lookup_objs(self): |     def test_deep_lookup_objs(self): | ||||||
|         self.assertSequenceEqual( |         self.assertSequenceEqual( | ||||||
|             JSONModel.objects.filter(field__k__l='m'), |             JSONModel.objects.filter(field__k__l='m'), | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user