AssetsTools.NET icon indicating copy to clipboard operation
AssetsTools.NET copied to clipboard

Deserialization of ExposedReference<Tile> leads to EndOfFileException

Open Albeoris opened this issue 1 year ago • 4 comments

During GetBaseField for this file:

result = AssetFileInfo
 ByteOffset = {long} 7687736
 ByteSize = {uint} 172
 IsReplacerPreviewable = {bool} false
 OldTypeId = {ushort} 0
 PathId = {long} 673
 Replacer = {IContentReplacer} null
 ReplacerType = {ContentReplacerType} None
 ScriptTypeIndex = {ushort} 0
 Stripped = {byte} 0
 TypeId = {int} 114
 TypeIdOrIndex = {int} 16

In the asset, I get EndOfFileException with such stack trace:

ThrowHelper.ThrowEndOfFileException()
Stream.ReadAtLeastCore()
BinaryReader.InternalRead()
BinaryReader.ReadInt64()
AssetsFileReader.ReadInt64()
AssetTypeTemplateField.ReadType() [7]
AssetTypeTemplateField.ReadType()
AssetTypeTemplateField.ReadType()
AssetTypeTemplateField.ReadType()
AssetTypeTemplateField.ReadType()
AssetTypeTemplateField.ReadType()
AssetTypeTemplateField.ReadType()
AssetTypeTemplateField.MakeValue()
AssetTypeTemplateField.MakeValue()
AssetsManager.GetBaseField()

The problem seems to have occurred when deserializing the "endTile" field because of strange PathId:

result = {List<AssetTypeValueField>} Count = 9
 [0] = {AssetTypeValueField} {Children: Count = 2  FieldName: "m_GameObject"  Value: null}
 [1] = {AssetTypeValueField} {Children: Count = 0  FieldName: "m_Enabled"  Value: {AsString: "1"}}
 [2] = {AssetTypeValueField} {Children: Count = 2  FieldName: "m_Script"  Value: null}
 [3] = {AssetTypeValueField} {Children: Count = 0  FieldName: "m_Name"  Value: {AsString: "Unit Movement Marker"}}
 [4] = {AssetTypeValueField} {Children: Count = 0  FieldName: "m_Time"  Value: {AsString: "33,6"}}
 [5] = {AssetTypeValueField} {Children: Count = 0  FieldName: "chosenPathType"  Value: {AsString: "1"}}
 [6] = {AssetTypeValueField} {Children: Count = 0  FieldName: "referenceType"  Value: {AsString: "0"}}
 [7] = {AssetTypeValueField} {Children: Count = 0  FieldName: "stopTimelineTillComplete"  Value: {AsString: "0"}}
 [8] = {AssetTypeValueField} {Children: Count = 1  FieldName: "endTile"  Value: null}
   [0] = {AssetTypeValueField} {Children: Count = 2  FieldName: "defaultValue"  Value: null}
     [0] = {AssetTypeValueField} {Children: Count = 0  FieldName: "m_FileID"  Value: {AsString: "10"}}
     [1] = {AssetTypeValueField} {Children: Count = 0  FieldName: "m_PathID"  Value: {AsString: "3834309553080054577"}}

And after that it led to an attempt to deserialize an array of the wrong size:

valueField = {AssetTypeValueField} {Children: Count = 3384  FieldName: "Array"  Value: null}
  Children = {List<AssetTypeValueField>} Count = 3384
  FieldName = {string} "Array"
capacity = {int} 13365
index = {int} 3384

This fields:

	[Token(Token = "0x4001D69")]
	[FieldOffset(Offset = "0x38")]
	[SerializeField]
	private ExposedReference<Tile> endTile;

	[Token(Token = "0x4001D6A")]
	[FieldOffset(Offset = "0x48")]
	[SerializeField]
	private ExposedReferenceHolder<Tile>[] tiles;

What can I do to help fix this problem?

Is there a way to disable the deserialization of certain types, as a workaround for problems like this?

Albeoris avatar Oct 15 '23 01:10 Albeoris

What can I do to help fix this problem?

MonoBehaviour issues are difficult to solve. If the class is simple enough, you can copy all of the classes with only the fields into a new Unity project, build a bundle using that monobehaviour, and checking the type tree using UABEA's file info dialog. There, you would be able to compare and see what the mono template generator missed. Since I don't have this game, I wouldn't be able to do it as it requires having the assemblies as well. I also don't have any time to attempt this right now.

Is there a way to disable the deserialization of certain types, as a workaround for problems like this?

If you mean skipping certain fields in a class, the answer is no. You have to read all fields in order because there's no information about how to skip over fields you don't want to read.

nesrak1 avatar Oct 15 '23 04:10 nesrak1

@nesrak1 I confirmed it with 2021.3.19f1.

There is a simple Unity project, build artifacts and simple test application: ExposedReference_Test.zip

I tried to...

checking the type tree using UABEA's file info dialog

...but UABEA has crashed with Null Reference Exception when I tried to export dump. :/

Albeoris avatar Oct 21 '23 22:10 Albeoris

...but UABEA has crashed with Null Reference Exception when I tried to export dump. :/

~~Make sure you're using nightly. There was a bug where certain versions were missing a field that wasn't null checked.~~

Ah, you said export dump. What I meant was Tools->Type Tree which shows the type tree for a given bundle (or just the list of types for non-bundles). The above suggestion only works for the Type Tree window.

nesrak1 avatar Oct 21 '23 22:10 nesrak1

Looks like PropertyName is special in that the C# struct stores the name as an int but it's actually serialized as a string. According to AssetStudio and AssetRipper, the only special case left to handle is SphericalHarmonicsL2.

Changes pushed for PropertyName for now.

nesrak1 avatar Oct 21 '23 23:10 nesrak1