Why does System.Formats.Nrbf.ArrayRecord.GetArray require the type of the object in the array? #108625
-
I'm using the prerelease Nrbf library from Nuget. It's not clear to me why I need to pass in the type into Here's a simple example. using System.Runtime.Serialization.Formatters.Binary;
using System.Formats.Nrbf;
namespace SerializerTest
{
[Serializable]
public class Bar
{
public string Name { get; set; }
}
[Serializable]
public class Foo
{
public string Name { get; set; }
Bar[] Bars { get; set; }
public static void Test()
{
Foo foo = new Foo
{
Name = "John",
Bars = new []
{
new Bar { Name = "Bar1" },
new Bar { Name = "Bar2" },
new Bar { Name = "Bar3" },
}
};
#pragma warning disable SYSLIB0011 // Type or member is obsolete
var bf = new BinaryFormatter();
#pragma warning restore SYSLIB0011 // Type or member is obsolete
var ms = new MemoryStream();
bf.Serialize(ms, foo);
ms.Position = 0;
SerializationRecord headerObject = NrbfDecoder.Decode(ms, null, true);
var cr = headerObject as ClassRecord;
Console.WriteLine($"### HEADER");
Console.WriteLine($"Name: {cr.GetString("<Name>k__BackingField")}");
var bars = cr.GetArrayRecord("<Bars>k__BackingField");
// possible to get this without knowing the type?
var _bars = bars.GetArray(typeof(Bar[]));
Console.WriteLine($"### BARS");
}
}
} In the case that I was generating the serialization data somewhere else I could just define this public class Bar
{
} and would be able to still read the Name member so it's not clear what the type accomplishes. |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 5 replies
-
This is safe because the code of the type has clearly no risk. It also guarantees that the payload doesn't contain other types. |
Beta Was this translation helpful? Give feedback.
-
Thank you for the response
In my example, if I have a single |
Beta Was this translation helpful? Give feedback.
-
I feel like I'm missing something here since I'm still confused... For fields
Compared to arrays
So in both cases I end up with a |
Beta Was this translation helpful? Give feedback.
-
Big thanks for using it and sharing your feedback! And appologies for such a late response (I was on a parental leave for a few weeks).
Short answer: There are multiple ways of attacking an app the reads payloads produced by Long answer: Just to give you one example of an attack: The NRBF format has a concept of a serialization record that represents multiple nulls with just a single Now imagine an app that expects an array of 20-40 integers. The developer checks the payload size and it's just 90 bytes, so it passes the payload to the
To be honest this is a scenario that I have not taken into account. The good news is that I expected arrays of classes to be most common use case and introduced Here is an example of using it: using System.Formats.Nrbf;
using System.Runtime.Serialization.Formatters.Binary;
namespace NrbfArrayOfClassses
{
internal class Program
{
static void Main(string[] args)
{
MyClass[] instances =
[
new MyClass() { Text = "Some", Index = 0 },
new MyClass() { Text = "Value", Index = 400 }
];
using MemoryStream payload = Serialize(instances);
SerializationRecord serializationRecord = NrbfDecoder.Decode(payload);
if (serializationRecord is SZArrayRecord<SerializationRecord> arrayOfRecords)
{
SerializationRecord[] arrayItems = arrayOfRecords.GetArray()!; // no need to specify type
foreach (SerializationRecord arrayItem in arrayItems)
{
if (arrayItem is ClassRecord classRecord)
{
Console.WriteLine($"TypeName: {classRecord.TypeName.FullName}, Text: {classRecord.GetString(nameof(MyClass.Text))}, Index: {classRecord.GetInt32(nameof(MyClass.Index))}");
}
}
}
}
protected static MemoryStream Serialize<T>(T instance) where T : notnull
{
MemoryStream ms = new();
#pragma warning disable SYSLIB0011 // Type or member is obsolete
new BinaryFormatter().Serialize(ms, instance);
#pragma warning restore SYSLIB0011 // Type or member is obsolete
ms.Position = 0;
return ms;
}
}
[Serializable]
public class MyClass
{
public string? Text;
public int Index;
}
} Note: In our case the
That was very clever! And thank you for sharing the workaround to get others unblocked. |
Beta Was this translation helpful? Give feedback.
GetArray
lets the NRBF library creates the array and objects for you. For security manner, it must not create a type that the caller code is not aware of.This is safe because the code of the type has clearly no risk. It also guarantees that the payload doesn't contain other types.