From 4849d7e4b03dd1f8bf012ac0f2fc230ca43b5bd2 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 16 Apr 2010 15:59:58 +0400 Subject: [PATCH] protect against SOE when iterating superclasses (PY-846) --- .../jetbrains/python/psi/impl/PyClassImpl.java | 17 ++++++++++++----- .../PyInitNewSignatureInspection/expected.xml | 3 +++ .../PyInitNewSignatureInspection/src/seoa.py | 4 ++++ .../PyInitNewSignatureInspection/src/seob.py | 4 ++++ .../jetbrains/python/PythonInspectionsTest.java | 7 ++++++- 5 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 python/testData/inspections/PyInitNewSignatureInspection/expected.xml create mode 100644 python/testData/inspections/PyInitNewSignatureInspection/src/seoa.py create mode 100644 python/testData/inspections/PyInitNewSignatureInspection/src/seob.py diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java index aba1a9ef39f9..b071aa1c7a32 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java @@ -529,8 +529,8 @@ public class PyClassImpl extends PyPresentableElementImpl implement } private static class AncestorsIterator implements Iterator { - List pending = new LinkedList(); - Set seen = new HashSet(); + List pending = new LinkedList(); + Set seen; Iterator percolator; PyClass prefetch = null; private final PyClassImpl myAClass; @@ -538,6 +538,13 @@ public class PyClassImpl extends PyPresentableElementImpl implement public AncestorsIterator(PyClassImpl aClass) { myAClass = aClass; percolator = myAClass.getSuperClassesList().iterator(); + seen = new HashSet(); + } + + private AncestorsIterator(PyClassImpl AClass, Set seen) { + myAClass = AClass; + this.seen = seen; + percolator = myAClass.getSuperClassesList().iterator(); } public boolean hasNext() { @@ -563,7 +570,7 @@ public class PyClassImpl extends PyPresentableElementImpl implement return ret; } if (percolator.hasNext()) { - PyClass it = percolator.next(); + PyClassImpl it = (PyClassImpl)percolator.next(); if (seen.contains(it)) { continue iterations; // loop back is equivalent to return next(); } @@ -572,9 +579,9 @@ public class PyClassImpl extends PyPresentableElementImpl implement return it; } else if (pending.size() > 0) { - PyClass it = pending.get(0); + PyClassImpl it = pending.get(0); pending.remove(0); // t, ts* = pending - percolator = it.iterateAncestors().iterator(); + percolator = new AncestorsIterator(it, new HashSet(seen)); // loop back is equivalent to return next(); } else return null; diff --git a/python/testData/inspections/PyInitNewSignatureInspection/expected.xml b/python/testData/inspections/PyInitNewSignatureInspection/expected.xml new file mode 100644 index 000000000000..580a889dbfd6 --- /dev/null +++ b/python/testData/inspections/PyInitNewSignatureInspection/expected.xml @@ -0,0 +1,3 @@ + + + diff --git a/python/testData/inspections/PyInitNewSignatureInspection/src/seoa.py b/python/testData/inspections/PyInitNewSignatureInspection/src/seoa.py new file mode 100644 index 000000000000..798d3e1ec453 --- /dev/null +++ b/python/testData/inspections/PyInitNewSignatureInspection/src/seoa.py @@ -0,0 +1,4 @@ +from seob import SeoB +class SeoA(SeoB): + pass + diff --git a/python/testData/inspections/PyInitNewSignatureInspection/src/seob.py b/python/testData/inspections/PyInitNewSignatureInspection/src/seob.py new file mode 100644 index 000000000000..0b12e942294f --- /dev/null +++ b/python/testData/inspections/PyInitNewSignatureInspection/src/seob.py @@ -0,0 +1,4 @@ +from seoa import SeoA +class SeoB(SeoA): + pass + diff --git a/python/testSrc/com/jetbrains/python/PythonInspectionsTest.java b/python/testSrc/com/jetbrains/python/PythonInspectionsTest.java index 833394e8ea3b..b75aeb98ffd8 100644 --- a/python/testSrc/com/jetbrains/python/PythonInspectionsTest.java +++ b/python/testSrc/com/jetbrains/python/PythonInspectionsTest.java @@ -16,7 +16,7 @@ public class PythonInspectionsTest extends PyLightFixtureTestCase { doTest(getTestName(true), inspection); } - private void doTest(String testName, LocalInspectionTool localInspectionTool) throws Throwable { + private void doTest(String testName, LocalInspectionTool localInspectionTool) throws Exception { myFixture.testInspection("inspections/" + testName, new LocalInspectionToolWrapper(localInspectionTool)); } @@ -180,4 +180,9 @@ public class PythonInspectionsTest extends PyLightFixtureTestCase { LocalInspectionTool inspection = new PyTupleItemAssignmentInspection(); doTest(getTestName(false), inspection); } + + public void testPyInitNewSignatureInspection() throws Exception { + LocalInspectionTool inspection = new PyInitNewSignatureInspection(); + doTest(getTestName(false), inspection); + } }