-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
No way to serialize an object of type System.Random #27429
Comments
cc @SteliosFly |
IMO a better design would be to allow public class Random {
public byte[] SerializeState();
public static Random DeserializeFrom(byte[] serializedState);
} |
I agree there is no need to bring binary formatter into this unless it is important for compatibility. @kcwalina do we have an established API pattern for serialization by custom means (eg into a byte array). I suppose not. Unless it's ISerializable which has too much binary formatter baggage. |
Does anyone know of a workaround that would allow us to serialize the state such that we could continue generating a consistent set of random numbers? |
cc @stephentoub , this came up today talking to ML folks. They have their own random generators, which they plan to made derived classes of |
@danmosemsft My proposal would not automatically work with derived types. That's by design. With my proposal the way you'd have to do it is through method hiding. DerivedRandom would also have a non-virtual serialize instance method and a static deserialize method. If you know that you have an instance of DerivedRandom rather than Random, you'd need to call the appropriate static deserialization method. Again, this is intentional, because it avoids deserialization exploits. |
@panesofglass The only options are not ugly, but really plain wrong. Either you manually extract and set the private fields of the randomizer or you need to wrap it with a class that holds the seed of the random, and on deserialization "replays" the calls on the In any case, the random algorithm is not part of the contract I think so it may change at any time. |
Clarified the title. I agree that there is no need to bring binary serialization into this. |
Is compatibility with .NET a consideration for this? A quick comparison suggests corefx uses the same algorithm as referencesource and thus .NET (which does have a serializable Random), so potentially Random instances could be compatibly serialized and deserialized. |
In general, we're loathe to mark types as |
If folks reading this issue would find @GrabYourPitchforks suggested API valuable, please thumbs up that post above. |
... damn. Back to .Net Framework I go, then :-(. Or I suppose I grab the source and make a serializable version. We've had working software for 14 years that uses this property of Random. Should I assume that binary serialization will no longer be supported in some future version of .Net Core? It'd be good to know now, so that we can move our core product entirely away from .Net towards some system such as Smalltalk with fast state load/save. |
@Ozzard Is there any reason the proposal at #27429 (comment) wouldn't work for your scenarios? |
One and a half, neither of which should necessarily stop it moving forward:
My use case is fast state dumps of simulations with up to about half a gigabyte of data, mostly small (10-200 byte) data objects, so that the simulations can be restarted from known points. The data forms a directed graph, neither tree-structured nor acyclic. It has to be fast because we're allowing users to interact with these things, and while we're dumping state we're unable to interact. 30 seconds is about our realistic upper limit. I couldn't care less about deserialization exploits; we have full control over the byte stream and the code in use at all points. I selected binary formatting because it did everything we needed without trying to satisfy ultimately unsatisfiable goals for fast state save such as security. |
This was my use case, as well. |
It's not impossible this API could get into 5.0 if its fairly clear it's the appropriate design, etc, someone championed it in API review, and there was a community volunteer to implement and get it merged into master all by July 15th.
Seems a pretty reasonable interim solution if it's the only thing holding you on .NET Framework. |
As mentioned above, we will not add @GrabYourPitchforks in the general case of an arbitrary serializer, what is our story? For our Json serializer, I guess our current story would be to write a converter explicitly, but ideally a type could support some recognized pattern. Our nearest thing to an API for "serialize/deserialize" is |
@danmosemsft There were some proposals floating around to allow serialization of arbitrary objects, but they never really took off. Generally speaking, for standard serialization the best thing is to stick to POCOs and primitives, plus simple collections like For types like |
@GrabYourPitchforks thanks, that is clear. Let's say we added those methods to Random that deal with byte arrays, then the consumer would have to ensure there was a converter for Random appropriate for their serializer of choice, right? @steveharter just curious, taking JSON serializer as the test case, do we imagine we would offer converters for types like this, or they would be externally supplied by app or some library it depends on? Just wondering how this ecosystem fits together. |
It'd be hooked up in the same way that any type not natively understood by the serializer gets hooked up. Write a custom converter, or define a separate property on your POCO which handles the translation for you: public class MySerializableClass
{
private Random _rnd;
public byte[] RngBytes
{
get => _rng.Serialize();
set => { _rng = Random.Deserialize(value); }
}
} |
OK. From discussing offline, it might also be interesting to consider whether we should have a general pattern that a type should implement to implement if it wants to serialize to/from bytes. This would not be for graphs - probably the type would contain only primitive fields, as Random does. @stephentoub we have no such pattern today do we? |
We have some types that accept bytes into constructors and expose bytes from properties/methods, e.g. |
This probably needs to be in its own topic, but it is related to the binary serializer and its current incarnation in .NET Core, so apologies up front for miss-posting. The changes/restrictions to the binary serializer is also preventing us from porting our commercial applications over to core; though, I completely agree with the overall sentiment and security concerns. However, in our case (and I expect others too), have used the binary serializer not so much for serialization, but as a deep cloner. In our app it is used for the following:
In all these cases, the internal representation of the serialization was never exposed, cared about, or saved externally. It would be very cool if .NET Core officially supported some standard deep cloning facility. We looked at many libraries, but none of them honored the binary serializer's attributes, special constructors, and callback interfaces which we need. Others used internal implementation details or had varying solutions depending on the version of .NET core being used (emit, expression trees, etc.), and/or carried a bunch of .NET Framework legacy code. We are currently in the process of writing this functionality, which we hope will unblock us and allow us to continue our transition to core. I’ve seen a bunch of these issues raised about or around the legacy binary serializer and just wanted to share some use cases that you might not be aware of that may be impacting others in conversion from the legacy .NET framework. Anyway, something to think about... Thanks much, |
@jpapp05 Do you have a scenario for cloning |
The later. For us at least, the issue with Since we are working around the issue there is no real ask here; just an observation from our own path to .NET core and the struggles we had with converting a large commercial application; ditching the binary serializer has by far been one of our biggest hurdles. Some type of deep cloning service might be a way for others to be unblocked, even if in this particular use case it does not really apply. |
@danmosemsft Is there, anywhere, a razor to decide between the following two options?
Also, can some kind soul point me to any expected replacement support for efficient object graph (de)serialization? I don't mind if it's a package - in fact I think it's probably better outside of .Net Core itself to make it unavailable to as many attackers as possible. But I'd be concerned if there are plans to drop this capability with no replacement. |
@GrabYourPitchforks is a better person than me to speak to the various serializers and their pros/cons. From the core libraries, you could look at DataContractSerializer |
DataContractSerializer is almost, but not quite, useful. Here's why:
The net effect of this is that the effort to secure BinaryFormatter also makes its closest replacement, DataContractSerializer, unusable. How likely is it that the team would accept DataContract markers for system classes such as Random? |
@danmosemsft Just to check, there was also the first part of my comment - any statement or documentation around a razor that can be applied consistently to deal with decisions between performance/functionality vs. security. Who would be well placed to comment on that, please, or is there anything already existing to which you could point me? Architecturally and commercially, I reckon it's critically important to understand a candidate technology's maintainers' views on that perennial nasty trade-off. |
Fair question and I'm looking to @GrabYourPitchforks to share that guidance. |
I am working on some public-facing guidance on this for serializer writers. But in a nutshell, there are three things that make In these examples I'll talk about
Some developers use a
Like I said, more should be coming on this over the next few weeks. |
We're winding down usage of Closing this issue for now. If there is interest after all in adding a serializable API surface for |
Code snippet to reproduce:
Error message:
Is it possible to add
System.Random
to the list of binary serializable types? We use this to save the state of a random generator while processing long-running ML tasks.The text was updated successfully, but these errors were encountered: