From 332709f9ee013e22bcdd3a0eae03c44c1da9ddd6 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Tue, 17 Feb 2015 16:46:35 +0300 Subject: [PATCH] Fixed SOE in PyClass.isOverriddenMRO() check (PY-15002) In Python 2 it is possible to create an endless metaclass chain by defining '__metaclass__' at the top-level to be one of the classes defined in the module. We assume that these circular metaclasses don't override `mro()` in order to prevent infinite recursion in this check. --- .../com/jetbrains/python/psi/impl/PyClassImpl.java | 3 +++ .../incorrectFileLevelMetaclass.py | 11 +++++++++++ .../PyUnresolvedReferencesInspectionTest.java | 5 +++++ 3 files changed, 19 insertions(+) create mode 100644 python/testData/inspections/PyUnresolvedReferencesInspection/incorrectFileLevelMetaclass.py diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java index 29e590bac898..33c7a7a40339 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java @@ -1359,6 +1359,9 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla final PyType metaClassType = cls.getMetaClassType(context); if (metaClassType instanceof PyClassType) { final PyClass metaClass = ((PyClassType)metaClassType).getPyClass(); + if (cls == metaClass) { + return false; + } final PyFunction mroMethod = metaClass.findMethodByName(PyNames.MRO, true); if (mroMethod != null) { final PyClass mroClass = mroMethod.getContainingClass(); diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/incorrectFileLevelMetaclass.py b/python/testData/inspections/PyUnresolvedReferencesInspection/incorrectFileLevelMetaclass.py new file mode 100644 index 000000000000..0e55981c2db4 --- /dev/null +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/incorrectFileLevelMetaclass.py @@ -0,0 +1,11 @@ +class __metaclass__(object): + pass + + +class C(object): + def foo(self): + pass + + +c = C() +c.foo() diff --git a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java index 327cecabf147..9013d0952934 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java @@ -460,6 +460,11 @@ public class PyUnresolvedReferencesInspectionTest extends PyInspectionTestCase { doTest(); } + // PY-15002 + public void testIncorrectFileLevelMetaclass() { + doTest(); + } + @NotNull @Override protected Class getInspectionClass() {