Commit 1f537335 authored by Anssi Kääriäinen's avatar Anssi Kääriäinen
Browse files

[1.4.x] Fixed #18979 -- Avoid endless loop caused by "val in PermLookupDict"

Fixed by defining __iter__ which raises TypeError. This was done to
PermWrapper earlier.

Backport of 50d573d2
parent bd514f28
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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 __nonzero__(self):
        return self.user.has_module_perms(self.module_name)

+44 −0
Original line number Diff line number Diff line
@@ -2,12 +2,56 @@ import os

from django.conf import global_settings
from django.contrib.auth import authenticate
from django.contrib.auth.context_processors import PermWrapper, PermLookupDict
from django.db.models import Q
from django.template import context
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


class AuthContextProcessorTests(TestCase):
    """
    Tests for the ``django.contrib.auth.context_processors.auth`` processor