vexe / VFW

MIT License
491 stars 67 forks source link

ReflectiveComponentSerializer is easy to break through infinite recursion #69

Open hymerman opened 8 years ago

hymerman commented 8 years ago

I'm finding that serializing any object that has a field of its own type causes ReflectiveComponentSerializer to recurse infinitely. This is using Vexe.FastSave.Save.ObjectToMemory to save some objects.

For example, System.TimeSpan which has a field public static readonly TimeSpan Zero, or System.Guid which has a field public static readonly Guid Empty, both trigger this behaviour.

I'd expect this behaviour if there genuinely were circular references (though even then it would be nice to detect!), but for these static readonly members it seems maybe easy to avoid.

Can you point me in the right direction to figure out how to fix this?

vexe commented 8 years ago

Are you using the standard mode for BinaryX20? It should handle cycles/serializing by reference. (See comments on SetMode function in BinaryX20.cs).

But you mentioned 'Guid', which is a struct, it's been a while maybe I'm not handling cycles for structs... Anyway, the way to handle that is check for cycles in the serializer code - or a much simpler way is to write a custom serializer to write/read Guid objects (e.g. StrongSerializer), that way it doesn't get serialized recursively. Just make sure then to add your serializer to the list of serializer when constructing BinaryX20. All you need to serializer a Guid is its byte or string data. See for example my GuidSerializer in my old FastSerializer https://github.com/vexe/FastSerializer/blob/master/FastSerializer/Serializers/GuidSerializer.cs

Let me know how that goes.

hymerman commented 8 years ago

Thanks for getting back to me!

Yes, this is using BinaryX20 in standard mode. And you're right, Guid and TimeSpan are both structs - so I imagine there's no cycle checking code for structs.

I don't think I'm confident enough with the internals of VFW to implement that yet so I had a go at adding custom serializers for both, and that seems to have done the trick - thanks!

I'll leave it up to you to decide whether to leave this issue open to track struct cycle checking, or just close it :)