30 lines
1.6 KiB
Diff
30 lines
1.6 KiB
Diff
Fixes django-0002: Serializer.serialize() — selected_fields list membership tested 3× per field per object.
|
||
|
||
--- a/django/core/serializers/base.py
|
||
+++ b/django/core/serializers/base.py
|
||
|
||
@@ DEFECT django-0002: Serializer.serialize() lines 102, 130, 136, 143
|
||
|
||
def serialize(self, queryset, *, stream=None, fields=None, use_natural_foreign_keys=False,
|
||
use_natural_primary_keys=False, progress_output=None, object_count=0):
|
||
...
|
||
- self.selected_fields = fields # raw list — CWE-407
|
||
+ self.selected_fields = frozenset(fields) if fields is not None else None # FIX django-0002
|
||
|
||
for count, obj in enumerate(queryset, start=1): # N objects
|
||
...
|
||
for field in concrete_model._meta.local_fields: # F fields
|
||
if field.serialize or field is pk_parent:
|
||
if field.remote_field is None:
|
||
if (
|
||
self.selected_fields is None
|
||
- or field.attname in self.selected_fields # O(S) list scan × 3 — CWE-407
|
||
+ or field.attname in self.selected_fields # O(1) frozenset — fixed
|
||
):
|
||
|
||
# BEFORE: selected_fields is a list; 3 × O(S) scans per field per object.
|
||
# Total: O(N × F × S) for N objects, F fields, S selected fields.
|
||
# AFTER: selected_fields is frozenset; 3 × O(1) per field per object.
|
||
# Total: O(N × F).
|
||
# Triggered by: dumpdata, loaddata, REST serialization, Django REST Framework compat.
|
||
# One-line fix; frozenset supports `in` identically to list.
|