From b68e7a1e5dc5cab7238663dbea9f812aca99c857 Mon Sep 17 00:00:00 2001 From: Arvid Bessen Date: Mon, 17 Oct 2016 21:17:50 -0400 Subject: [PATCH] Calling isinstance(x,t) repeatedly when x or t is not actually a CLR object will leak reference counts to PyFalse, resulting in memory corruption once the reference count drops to zero and PyFalse gets freed --- src/runtime/metatype.cs | 12 +++++++++--- src/tests/test_subclass.py | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/runtime/metatype.cs b/src/runtime/metatype.cs index 8b062ee59..2bd8cda0d 100644 --- a/src/runtime/metatype.cs +++ b/src/runtime/metatype.cs @@ -281,8 +281,10 @@ static IntPtr DoInstanceCheck(IntPtr tp, IntPtr args, bool checkType) { ClassBase cb = GetManagedObject(tp) as ClassBase; - if (cb == null) + if (cb == null) { + Runtime.Incref(Runtime.PyFalse); return Runtime.PyFalse; + } using (PyList argsObj = new PyList(args)) { @@ -296,12 +298,16 @@ static IntPtr DoInstanceCheck(IntPtr tp, IntPtr args, bool checkType) else otherType = arg.GetPythonType(); - if (Runtime.PyObject_TYPE(otherType.Handle) != PyCLRMetaType) + if (Runtime.PyObject_TYPE(otherType.Handle) != PyCLRMetaType) { + Runtime.Incref(Runtime.PyFalse); return Runtime.PyFalse; + } ClassBase otherCb = GetManagedObject(otherType.Handle) as ClassBase; - if (otherCb == null) + if (otherCb == null) { + Runtime.Incref(Runtime.PyFalse); return Runtime.PyFalse; + } return Converter.ToPython(cb.type.IsAssignableFrom(otherCb.type)); } diff --git a/src/tests/test_subclass.py b/src/tests/test_subclass.py index 43e8fb7aa..c486a0fc3 100644 --- a/src/tests/test_subclass.py +++ b/src/tests/test_subclass.py @@ -147,6 +147,21 @@ def handler(self, x, args): self.assertEqual(event_handler.value, 3) self.assertEqual(len(d.event_handlers), 1) + def test_isinstance(self): + from System import Object + from System import String + + a = [str(x) for x in range(0, 1000)] + b = [String(x) for x in a] + + for x in a: + self.assertFalse(isinstance(x, Object)) + self.assertFalse(isinstance(x, String)) + + for x in b: + self.assertTrue(isinstance(x, Object)) + self.assertTrue(isinstance(x, String)) + def test_suite(): return unittest.makeSuite(SubClassTests)