From 50d573d2c0b3e17cbf1aa240b03b52e4ad0c32cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anssi=20K=C3=A4=C3=A4ri=C3=A4inen?= Date: Thu, 27 Sep 2012 15:36:30 +0300 Subject: [PATCH] Fixed #18979 -- Avoid endless loop caused by "val in PermLookupDict" Fixed by defining __iter__ which raises TypeError. This was done to PermWrapper earlier. --- django/contrib/auth/context_processors.py | 5 +++ .../contrib/auth/tests/context_processors.py | 44 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/django/contrib/auth/context_processors.py b/django/contrib/auth/context_processors.py index 1b6c2eedd0..77face01a7 100644 --- a/django/contrib/auth/context_processors.py +++ b/django/contrib/auth/context_processors.py @@ -11,6 +11,11 @@ class PermLookupDict(object): def __getitem__(self, perm_name): return self.user.has_perm("%s.%s" % (self.module_name, perm_name)) + def __iter__(self): + # To fix 'item in perms.someapp' and __getitem__ iteraction we need to + # define __iter__. See #18979 for details. + raise TypeError("PermLookupDict is not iterable.") + def __bool__(self): return self.user.has_module_perms(self.module_name) __nonzero__ = __bool__ # Python 2 diff --git a/django/contrib/auth/tests/context_processors.py b/django/contrib/auth/tests/context_processors.py index 4e914133d0..8d87e0ae15 100644 --- a/django/contrib/auth/tests/context_processors.py +++ b/django/contrib/auth/tests/context_processors.py @@ -3,11 +3,55 @@ import os from django.conf import global_settings from django.contrib.auth import authenticate from django.contrib.auth.tests.utils import skipIfCustomUser +from django.contrib.auth.context_processors import PermWrapper, PermLookupDict from django.db.models import Q from django.test import TestCase from django.test.utils import override_settings +class MockUser(object): + def has_module_perm(self, perm): + if perm == 'mockapp.someapp': + return True + return False + + def has_perm(self, perm): + if perm == 'someperm': + return True + return False + + +class PermWrapperTests(TestCase): + """ + Test some details of the PermWrapper implementation. + """ + class EQLimiterObject(object): + """ + This object makes sure __eq__ will not be called endlessly. + """ + def __init__(self): + self.eq_calls = 0 + + def __eq__(self, other): + if self.eq_calls > 0: + return True + self.eq_calls += 1 + return False + + def test_permwrapper_in(self): + """ + Test that 'something' in PermWrapper doesn't end up in endless loop. + """ + perms = PermWrapper(MockUser()) + with self.assertRaises(TypeError): + self.EQLimiterObject() in perms + + def test_permlookupdict_in(self): + pldict = PermLookupDict(MockUser(), 'mockapp') + with self.assertRaises(TypeError): + self.EQLimiterObject() in pldict + + @skipIfCustomUser @override_settings( TEMPLATE_DIRS=(