Opened 9 years ago
Closed 9 years ago
#27198 closed Bug (fixed)
QueryDict getlist allows data to be mutated
| Reported by: | Fraser Nevett | Owned by: | Jani Tiainen |
|---|---|---|---|
| Component: | HTTP handling | Version: | 1.10 |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Accepted | |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Calling getlist() on a QueryDict simply returns the underlying list, which means it can be mutated:
>>> q = QueryDict('a=1&a=2&a=3', mutable=False)
>>> a = q.getlist('a')
>>> a
[u'1', u'2', u'3']
>>> a.append(u'4')
>>> q.getlist('a')
[u'1', u'2', u'3', u'4']
>>> q
<QueryDict: {u'a': [u'1', u'2', u'3', u'4']}>
I encountered this unexpected behaviour in code using the following pattern:
values = request.POST.getlist('a')
values += request.POST.getlist('b')
values += request.POST.getlist('c')
This results in request.POST being updated so that a now also contains the values for b and c.
Given request.GET and request.POST are created as immutable QueryDict objects, I would not expect this behaviour.
At present, getlist is inherited from MultiValueDict. I think the fix would be to add a getlist method to QueryDict that forces a new list to be created:
def setlist(self, key, default=None):
return list(super(QueryDict, self).getlist(key, default))
Attachments (1)
Change History (6)
comment:1 by , 9 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|
by , 9 years ago
| Attachment: | 27198-test.diff added |
|---|
comment:2 by , 9 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
comment:3 by , 9 years ago
| Has patch: | set |
|---|
Agreed that doesn't seem correct. Attached is a regression test for Django's test suite that currently fails.