From b3d4f6929e4f1e9e7fe3c808dad394d932a0a737 Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 5 Nov 2020 11:42:45 +0800 Subject: [PATCH] Prevent ApiTypeNameHelper infinite loop. --- framework/Volo.Abp.sln | 7 +++ .../Abp/Http/Modeling/ApiTypeNameHelper.cs | 29 ++++++++---- .../Volo.Abp.Http.Tests.csproj | 16 +++++++ .../Volo/Abp/Http/AbpHttpTestModule.cs | 10 +++++ .../Volo/Abp/Http/ApiTypeNameHelper_Tests.cs | 44 +++++++++++++++++++ 5 files changed, 98 insertions(+), 8 deletions(-) create mode 100644 framework/test/Volo.Abp.Http.Tests/Volo.Abp.Http.Tests.csproj create mode 100644 framework/test/Volo.Abp.Http.Tests/Volo/Abp/Http/AbpHttpTestModule.cs create mode 100644 framework/test/Volo.Abp.Http.Tests/Volo/Abp/Http/ApiTypeNameHelper_Tests.cs diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln index 6957eb2baf..963472ada8 100644 --- a/framework/Volo.Abp.sln +++ b/framework/Volo.Abp.sln @@ -357,6 +357,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Swashbuckle", "src EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Json.Tests", "test\Volo.Abp.Json.Tests\Volo.Abp.Json.Tests.csproj", "{00D07595-993C-40FC-BD90-0DD6331414D3}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Http.Tests", "test\Volo.Abp.Http.Tests\Volo.Abp.Http.Tests.csproj", "{A37BFEB5-7C57-4CDC-93B8-B5CE4BB9ACE1}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1063,6 +1065,10 @@ Global {00D07595-993C-40FC-BD90-0DD6331414D3}.Debug|Any CPU.Build.0 = Debug|Any CPU {00D07595-993C-40FC-BD90-0DD6331414D3}.Release|Any CPU.ActiveCfg = Release|Any CPU {00D07595-993C-40FC-BD90-0DD6331414D3}.Release|Any CPU.Build.0 = Release|Any CPU + {A37BFEB5-7C57-4CDC-93B8-B5CE4BB9ACE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A37BFEB5-7C57-4CDC-93B8-B5CE4BB9ACE1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A37BFEB5-7C57-4CDC-93B8-B5CE4BB9ACE1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A37BFEB5-7C57-4CDC-93B8-B5CE4BB9ACE1}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1243,6 +1249,7 @@ Global {89840441-5A3A-4FD7-9CB4-E5B52FAEF72A} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {DD9519E0-5A68-48DC-A051-7BF2AC922F3E} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {00D07595-993C-40FC-BD90-0DD6331414D3} = {447C8A77-E5F0-4538-8687-7383196D04EA} + {A37BFEB5-7C57-4CDC-93B8-B5CE4BB9ACE1} = {447C8A77-E5F0-4538-8687-7383196D04EA} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} diff --git a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ApiTypeNameHelper.cs b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ApiTypeNameHelper.cs index 46eb9e903d..04467712a9 100644 --- a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ApiTypeNameHelper.cs +++ b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ApiTypeNameHelper.cs @@ -1,20 +1,28 @@ using System; +using Volo.Abp.Collections; using Volo.Abp.Reflection; namespace Volo.Abp.Http.Modeling { public static class ApiTypeNameHelper { + private static ITypeList _cycleType = new TypeList(); + public static string GetTypeName(Type type) { if (TypeHelper.IsDictionary(type, out var keyType, out var valueType)) { - return $"{{{GetTypeName(keyType)}:{GetTypeName(valueType)}}}"; + if (keyType != type && valueType != type) + { + return $"{{{GetTypeName(keyType)}:{GetTypeName(valueType)}}}"; + } } - - if (TypeHelper.IsEnumerable(type, out var itemType, includePrimitives: false)) + else if (TypeHelper.IsEnumerable(type, out var itemType, includePrimitives: false)) { - return $"[{GetTypeName(itemType)}]"; + if (itemType != type) + { + return $"[{GetTypeName(itemType)}]"; + } } return TypeHelper.GetFullNameHandlingNullableAndGenerics(type); @@ -24,12 +32,17 @@ namespace Volo.Abp.Http.Modeling { if (TypeHelper.IsDictionary(type, out var keyType, out var valueType)) { - return $"{{{GetSimpleTypeName(keyType)}:{GetSimpleTypeName(valueType)}}}"; + if (keyType != type && valueType != type) + { + return $"{{{GetSimpleTypeName(keyType)}:{GetSimpleTypeName(valueType)}}}"; + } } - - if (TypeHelper.IsEnumerable(type, out var itemType, includePrimitives: false)) + else if (TypeHelper.IsEnumerable(type, out var itemType, includePrimitives: false)) { - return $"[{GetSimpleTypeName(itemType)}]"; + if (itemType != type) + { + return $"[{GetSimpleTypeName(itemType)}]"; + } } return TypeHelper.GetSimplifiedName(type); diff --git a/framework/test/Volo.Abp.Http.Tests/Volo.Abp.Http.Tests.csproj b/framework/test/Volo.Abp.Http.Tests/Volo.Abp.Http.Tests.csproj new file mode 100644 index 0000000000..e5b4898396 --- /dev/null +++ b/framework/test/Volo.Abp.Http.Tests/Volo.Abp.Http.Tests.csproj @@ -0,0 +1,16 @@ + + + + + + net5.0 + + + + + + + + + + diff --git a/framework/test/Volo.Abp.Http.Tests/Volo/Abp/Http/AbpHttpTestModule.cs b/framework/test/Volo.Abp.Http.Tests/Volo/Abp/Http/AbpHttpTestModule.cs new file mode 100644 index 0000000000..5eb7548277 --- /dev/null +++ b/framework/test/Volo.Abp.Http.Tests/Volo/Abp/Http/AbpHttpTestModule.cs @@ -0,0 +1,10 @@ +using Volo.Abp.Modularity; + +namespace Volo.Abp.Http +{ + [DependsOn(typeof(AbpHttpModule))] + public class AbpHttpTestModule : AbpModule + { + + } +} diff --git a/framework/test/Volo.Abp.Http.Tests/Volo/Abp/Http/ApiTypeNameHelper_Tests.cs b/framework/test/Volo.Abp.Http.Tests/Volo/Abp/Http/ApiTypeNameHelper_Tests.cs new file mode 100644 index 0000000000..45efde8b08 --- /dev/null +++ b/framework/test/Volo.Abp.Http.Tests/Volo/Abp/Http/ApiTypeNameHelper_Tests.cs @@ -0,0 +1,44 @@ +using System.Collections; +using System.Collections.Generic; +using Shouldly; +using Volo.Abp.Http.Modeling; +using Volo.Abp.Reflection; +using Xunit; + +namespace Volo.Abp.Http +{ + public class ApiTypeNameHelper_Tests + { + [Fact] + public void GetTypeName_Test() + { + ApiTypeNameHelper.GetTypeName(typeof(CycleClass)).ShouldBe(TypeHelper.GetFullNameHandlingNullableAndGenerics(typeof(CycleClass))); + ApiTypeNameHelper.GetTypeName(typeof(CycleClass2)).ShouldBe(TypeHelper.GetFullNameHandlingNullableAndGenerics(typeof(CycleClass2))); + } + + [Fact] + public void GetSimpleTypeName_Test() + { + ApiTypeNameHelper.GetSimpleTypeName(typeof(CycleClass)).ShouldBe(TypeHelper.GetSimplifiedName(typeof(CycleClass))); + ApiTypeNameHelper.GetSimpleTypeName(typeof(CycleClass2)).ShouldBe(TypeHelper.GetSimplifiedName(typeof(CycleClass2))); + } + + class CycleClass : IEnumerable + { + public IEnumerator GetEnumerator() + { + yield return new CycleClass(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } + + class CycleClass2 : Dictionary + { + + } + } +}