Opened 12 years ago

Closed 12 years ago

Last modified 12 years ago

#20068 closed Bug (needsinfo)

calling QueryDict.update with self causes an infinite loop

Reported by: anonymous Owned by: nobody
Component: Utilities Version: dev
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 by Aymeric Augustin, 12 years ago

Resolution: needsinfo
Status: newclosed

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 by Aymeric Augustin, 12 years ago

Component: UncategorizedUtilities
Type: UncategorizedBug

comment:3 by anonymous, 12 years ago

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 by Karen Tracey, 12 years ago

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 by anonymous, 12 years ago

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 by Aymeric Augustin, 12 years ago

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