Opened 2 years ago

Closed 2 years ago

Last modified 2 years ago

#20068 closed Bug (needsinfo)

calling QueryDict.update with self causes an infinite loop

Reported by: anonymous Owned by: nobody
Component: Utilities Version: master
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

In the following example:

q = QueryDict()
q.update(q)

the second line will cause an infinite loop. (Obviously there's a strong answer you just shouldn't do this...)

Regular python dictionaries appear to do nothing when updated with themselves. The appropriate fix would probably be to change the function update() in utils/datastructures.py around line 426-467 so that
other_dict = args[0]
if other_dict is self: return

(I don't have a github account so can't submit this change directly - sorry!) Making an appropriate test-case is less obvious, since it would involve detecting when the existing code runs forever.

Change History (6)

comment:1 Changed 2 years ago by aaugustin

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Resolution set to needsinfo
  • Status changed from new to closed

I couldn't reproduce the infinite recursion:

>>> from django.http import QueryDict
>>> qd = QueryDict("foo=bar")
>>> qd
<QueryDict: {u'foo': [u'bar']}>
>>> qd.update(qd)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/Users/myk/Documents/dev/django/django/utils/datastructures.py", line 429, in update
    self.setlistdefault(key).extend(value_list)
  File "/Users/myk/Documents/dev/django/django/http/request.py", line 335, in setlistdefault
    self._assert_mutable()
  File "/Users/myk/Documents/dev/django/django/http/request.py", line 303, in _assert_mutable
    raise AttributeError("This QueryDict instance is immutable")
AttributeError: This QueryDict instance is immutable

How do you trigger it?

comment:2 Changed 2 years ago by aaugustin

  • Component changed from Uncategorized to Utilities
  • Type changed from Uncategorized to Bug

comment:3 Changed 2 years ago by anonymous

In [1]: from django.http import QueryDict
In [2]: qd = QueryDict("foo=bar")
In [3]: qd2 = qd.copy()
In [4]: qd2.update(qd2)

At which point it runs forever. I hadn't realised they started off immutable, sorry (probably should have checked the exact example code given)

comment:4 Changed 2 years ago by kmtracey

I cannot recreate this even with updated instructions:

Python 2.7.3 (default, Aug  1 2012, 05:16:07) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.http import QueryDict
>>> qd = QueryDict("foo=bar")
>>> qd2 = qd.copy()
>>> qd2.update(qd2)
>>> qd2
<QueryDict: {u'foo': [u'bar', u'bar']}>
>>> import django
>>> django.get_version()
'1.6.dev20130318201629'
>>> 

comment:5 Changed 2 years ago by anonymous

Having done a more thorough check, it's fixed in stable/1.5.x and the current git master, but fails in 1.4.x. (The version given by django.get_version() is 1.4.5). The git check-in which fixes it seems to be 8f002867b2 ("Cleaned up the QueryDict implementation.").

It doesn't seem terribly likely that anyone else is likely to come across this bug in a slightly old version, and since I don't think there's a good reason to call update on self (I only did it by mistake since I hadn't realised the two QueryDicts were the same) it may well not be worth fixing in 1.4.x.

Thanks for looking into it.

comment:6 Changed 2 years ago by aaugustin

1.4 only gets security fixes at this point, and this isn't a security issue.

https://docs.djangoproject.com/en/dev/internals/release-process/#supported-versions

Thanks for reporting it anyway!

Note: See TracTickets for help on using tickets.
Back to Top