From aedcb88f691aad0141f8f0c2c312bcf8e0b9d3c0 Mon Sep 17 00:00:00 2001 From: Victor Nova Date: Tue, 30 Mar 2021 14:45:04 -0700 Subject: [PATCH 1/3] added regression test for https://github.com/pythonnet/pythonnet/issues/1427 (stack overflow trying to pass `System.Type` to `CanEncode`) --- src/embed_tests/Codecs.cs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/embed_tests/Codecs.cs b/src/embed_tests/Codecs.cs index 266badb9e..ce837d481 100644 --- a/src/embed_tests/Codecs.cs +++ b/src/embed_tests/Codecs.cs @@ -296,6 +296,31 @@ public void IterableDecoderTest() Assert.DoesNotThrow(() => { codec.TryDecode(pyList, out intEnumerable); }); CollectionAssert.AreEqual(intEnumerable, new List { 1, 2, 3 }); } + + // regression for https://github.com/pythonnet/pythonnet/issues/1427 + [Test] + public void PythonRegisteredDecoder_NoStackOverflowOnSystemType() + { + const string PyCode = @" +import clr +import System +from Python.Runtime import PyObjectConversions +from Python.Runtime.Codecs import RawProxyEncoder + + +class ListAsRawEncoder(RawProxyEncoder): + __namespace__ = 'Dummy' + def CanEncode(self, clr_type): + return clr_type.Name == 'IList`1' and clr_type.Namespace == 'System.Collections.Generic' + + +list_encoder = ListAsRawEncoder() +PyObjectConversions.RegisterEncoder(list_encoder) + +system_type = list_encoder.GetType()"; + + PythonEngine.Exec(PyCode); + } } /// From ae3477d63a0a6b6c20974b9a60d8a8fe4e7fd70e Mon Sep 17 00:00:00 2001 From: Victor Nova Date: Tue, 30 Mar 2021 15:03:40 -0700 Subject: [PATCH 2/3] disabled ability to register encoders for `System.Type` Without this restriction encoders created in Python cause stack overflow due to repeated attempts to pass `System.Type` instance to `CanDecode`, which requires encoding the instance of `System.Type`, et. cetera fixes https://github.com/pythonnet/pythonnet/issues/1427 --- CHANGELOG.md | 1 + src/runtime/converter.cs | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5f262620..b565fbbdf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ One must now either use enum members (e.g. `MyEnum.Option`), or use enum constru - Sign Runtime DLL with a strong name - Implement loading through `clr_loader` instead of the included `ClrModule`, enables support for .NET Core +- BREAKING: custom encoders are no longer called for instances of `System.Type` ### Fixed diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs index 4de334b5f..cd9477a62 100644 --- a/src/runtime/converter.cs +++ b/src/runtime/converter.cs @@ -146,8 +146,11 @@ internal static IntPtr ToPython(object value, Type type) return result; } - if (Type.GetTypeCode(type) == TypeCode.Object && value.GetType() != typeof(object) - || type.IsEnum) { + if (Type.GetTypeCode(type) == TypeCode.Object + && value.GetType() != typeof(object) + && value is not Type + || type.IsEnum + ) { var encoded = PyObjectConversions.TryEncode(value, type); if (encoded != null) { result = encoded.Handle; From 0d33a9074b62b33457d577c9df0240f0a33f0a9c Mon Sep 17 00:00:00 2001 From: Victor Nova Date: Tue, 30 Mar 2021 20:59:53 -0700 Subject: [PATCH 3/3] disabled PythonRegisteredDecoder_NoStackOverflowOnSystemType test due to known issue with custom codes + engine restarts https://github.com/pythonnet/pythonnet/issues/1256 --- src/embed_tests/Codecs.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/embed_tests/Codecs.cs b/src/embed_tests/Codecs.cs index ce837d481..de5882b32 100644 --- a/src/embed_tests/Codecs.cs +++ b/src/embed_tests/Codecs.cs @@ -298,6 +298,7 @@ public void IterableDecoderTest() } // regression for https://github.com/pythonnet/pythonnet/issues/1427 + [Ignore("https://github.com/pythonnet/pythonnet/issues/1256")] [Test] public void PythonRegisteredDecoder_NoStackOverflowOnSystemType() {