Prevent infinite recursion when constructing MonoType

This commit is contained in:
ds5678 2024-09-19 22:35:07 -07:00
parent cc663f7b58
commit a9d2a43357
3 changed files with 43 additions and 18 deletions

View File

@ -300,8 +300,15 @@ internal static class AssetAPI
return failureTask;
}
string text = new DefaultJsonWalker().SerializeStandard(asset);
return Results.Text(text, "application/json").ExecuteAsync(context);
try
{
string text = new DefaultJsonWalker().SerializeStandard(asset);
return Results.Text(text, "application/json").ExecuteAsync(context);
}
catch (Exception ex)
{
return Results.Text(ex.ToString()).ExecuteAsync(context);
}
}
#endregion
@ -318,17 +325,24 @@ internal static class AssetAPI
return failureTask;
}
string text;
using (StringWriter stringWriter = new(CultureInfo.InvariantCulture) { NewLine = "\n" })
try
{
YamlWriter writer = new();
writer.WriteHead(stringWriter);
YamlDocument document = new YamlWalker().ExportYamlDocument(asset, ExportIdHandler.GetMainExportID(asset));
writer.WriteDocument(document);
writer.WriteTail(stringWriter);
text = stringWriter.ToString();
string text;
using (StringWriter stringWriter = new(CultureInfo.InvariantCulture) { NewLine = "\n" })
{
YamlWriter writer = new();
writer.WriteHead(stringWriter);
YamlDocument document = new YamlWalker().ExportYamlDocument(asset, ExportIdHandler.GetMainExportID(asset));
writer.WriteDocument(document);
writer.WriteTail(stringWriter);
text = stringWriter.ToString();
}
return Results.Text(text, "application/yaml").ExecuteAsync(context);
}
catch (Exception ex)
{
return Results.Text(ex.ToString()).ExecuteAsync(context);
}
return Results.Text(text, "application/yaml").ExecuteAsync(context);
}
#endregion

View File

@ -1,4 +1,5 @@
using AsmResolver.DotNet;
using AsmResolver.DotNet.Signatures;
using AssetRipper.Import.Structure.Assembly.Mono;
using AssetRipper.Import.Structure.Assembly.Serializable;
using AssetRipper.Import.Structure.Platforms;
@ -15,7 +16,7 @@ namespace AssetRipper.Import.Structure.Assembly.Managers
protected readonly Dictionary<string, AssemblyDefinition?> m_assemblies = new();
protected readonly Dictionary<AssemblyDefinition, Stream> m_assemblyStreams = new();
protected readonly Dictionary<string, bool> m_validTypes = new();
private readonly Dictionary<TypeDefinition, MonoType> monoTypeCache = new();
private readonly Dictionary<ITypeDefOrRef, MonoType> monoTypeCache = new(SignatureComparer.Default);
private event Action<string> m_requestAssemblyCallback;
private readonly Dictionary<string, SerializableType> m_serializableTypes = new();

View File

@ -22,7 +22,7 @@ namespace AssetRipper.Import.Structure.Assembly.Mono
public static bool TryCreate(
TypeDefinition typeDefinition,
Dictionary<TypeDefinition, MonoType> typeCache,
Dictionary<ITypeDefOrRef, MonoType> typeCache,
[NotNullWhen(true)] out MonoType? result,
[NotNullWhen(false)] out string? failureReason)
{
@ -61,11 +61,15 @@ namespace AssetRipper.Import.Structure.Assembly.Mono
public static bool TryCreate(
GenericInstanceTypeSignature genericInst,
Dictionary<TypeDefinition, MonoType> typeCache,
Dictionary<ITypeDefOrRef, MonoType> typeCache,
[NotNullWhen(true)] out MonoType? result,
[NotNullWhen(false)] out string? failureReason)
{
List<Field> fields = new();
result = new(genericInst.GenericType, fields);
typeCache.Add(genericInst.ToTypeDefOrRef(), result);
foreach ((FieldDefinition fieldDefinition, TypeSignature fieldType) in FieldQuery.GetFieldsInTypeAndBase(genericInst))
{
if (FieldSerializationLogic.WillUnitySerialize(fieldDefinition, fieldType))
@ -80,13 +84,13 @@ namespace AssetRipper.Import.Structure.Assembly.Mono
}
else
{
typeCache.Remove(genericInst.ToTypeDefOrRef());
result = null;
return false;
}
}
}
result = new(genericInst.GenericType, fields);
failureReason = null;
return true;
}
@ -109,7 +113,7 @@ namespace AssetRipper.Import.Structure.Assembly.Mono
private static bool TryCreateSerializableField(
FieldDefinition fieldDefinition,
TypeSignature fieldType,
Dictionary<TypeDefinition, MonoType> typeCache,
Dictionary<ITypeDefOrRef, MonoType> typeCache,
out Field result,
[NotNullWhen(false)] out string? failureReason)
{
@ -126,7 +130,7 @@ namespace AssetRipper.Import.Structure.Assembly.Mono
string name,
TypeSignature typeSignature,
int arrayDepth,
Dictionary<TypeDefinition, MonoType> typeCache,
Dictionary<ITypeDefOrRef, MonoType> typeCache,
out Field result,
[NotNullWhen(false)] out string? failureReason)
{
@ -181,6 +185,12 @@ namespace AssetRipper.Import.Structure.Assembly.Mono
return TryCreateSerializableField(name, szArrayTypeSignature.BaseType, arrayDepth + 1, typeCache, out result, out failureReason);
case GenericInstanceTypeSignature genericInstanceTypeSignature:
if (typeCache.TryGetValue(genericInstanceTypeSignature.ToTypeDefOrRef(), out MonoType? cachedGenericMonoType))
{
result = new Field(cachedGenericMonoType, arrayDepth, name, true);
failureReason = null;
return true;
}
return TryCreateSerializableField(name, genericInstanceTypeSignature, arrayDepth, typeCache, out result, out failureReason);
default:
@ -194,7 +204,7 @@ namespace AssetRipper.Import.Structure.Assembly.Mono
string name,
GenericInstanceTypeSignature typeSignature,
int arrayDepth,
Dictionary<TypeDefinition, MonoType> typeCache,
Dictionary<ITypeDefOrRef, MonoType> typeCache,
out Field result,
[NotNullWhen(false)] out string? failureReason)
{