Skip to content

Commit d17e0d0

Browse files
Adam Sitnikcarlossanlop
authored andcommitted
Bypassing Serialization Binders with BinaryFormatter Mutation
1 parent c1b0b27 commit d17e0d0

File tree

2 files changed

+31
-7
lines changed

2 files changed

+31
-7
lines changed

src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectWriter.cs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ private void WriteMembers(NameInfo memberNameInfo,
375375
return;
376376
}
377377

378-
if (!WriteKnownValueClass(memberNameInfo, memberTypeNameInfo, memberData!))
378+
if (!WriteKnownValueClass(memberNameInfo, memberTypeNameInfo, memberData!, ref assignUniqueIdToValueType))
379379
{
380380
if (outType == null)
381381
{
@@ -624,10 +624,10 @@ private void WriteArrayMember(WriteObjectInfo objectInfo, NameInfo arrayElemType
624624
actualTypeInfo._isArrayItem = true;
625625
}
626626

627-
if (!WriteKnownValueClass(arrayElemTypeNameInfo, actualTypeInfo, data!))
627+
bool assignUniqueIdForValueTypes = false;
628+
if (!WriteKnownValueClass(arrayElemTypeNameInfo, actualTypeInfo, data!, ref assignUniqueIdForValueTypes))
628629
{
629630
object obj = data!;
630-
bool assignUniqueIdForValueTypes = false;
631631
if (ReferenceEquals(arrayElemTypeNameInfo._type, Converter.s_typeofObject))
632632
{
633633
assignUniqueIdForValueTypes = true;
@@ -807,11 +807,12 @@ private long Schedule(object obj, bool assignUniqueIdToValueType, Type? type, Wr
807807
}
808808

809809
// Determines if a type is a primitive type, if it is it is written
810-
private bool WriteKnownValueClass(NameInfo memberNameInfo, NameInfo typeNameInfo, object data)
810+
private bool WriteKnownValueClass(NameInfo memberNameInfo, NameInfo typeNameInfo, object data, ref bool assignUniqueIdToValueType)
811811
{
812812
if (ReferenceEquals(typeNameInfo._type, Converter.s_typeofString))
813813
{
814814
WriteString(memberNameInfo, typeNameInfo, data);
815+
return true;
815816
}
816817
else
817818
{
@@ -825,18 +826,22 @@ private bool WriteKnownValueClass(NameInfo memberNameInfo, NameInfo typeNameInfo
825826
if (typeNameInfo._isArray) // null if an array
826827
{
827828
_serWriter.WriteItem(memberNameInfo, typeNameInfo, data);
829+
return true;
828830
}
829-
else
831+
else if (memberNameInfo._type == typeNameInfo._type
832+
|| memberNameInfo._type == typeof(object)
833+
|| (memberNameInfo._type != null && Nullable.GetUnderlyingType(memberNameInfo._type) != null))
830834
{
831835
_serWriter.WriteMember(memberNameInfo, typeNameInfo, data);
836+
return true;
832837
}
833838
}
834839
}
835840

836-
return true;
841+
assignUniqueIdToValueType = true;
842+
return false;
837843
}
838844

839-
840845
// Writes an object reference to the stream.
841846
private void WriteObjectRef(NameInfo nameInfo, long objectId) =>
842847
_serWriter!.WriteMemberObjectRef(nameInfo, (int)objectId);

src/libraries/System.Runtime.Serialization.Formatters/tests/BinaryFormatterTests.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,25 @@ public void Roundtrip_ArrayContainingArrayAtNonZeroLowerBound()
535535
BinaryFormatterHelpers.Clone(Array.CreateInstance(typeof(uint[]), new[] { 5 }, new[] { 1 }));
536536
}
537537

538+
[Fact]
539+
[SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, ".NET Framework has not been patched yet.")]
540+
public void BypassingSerializationBinders()
541+
{
542+
Tuple<IComparable, object> tuple = new Tuple<IComparable, object>(42, new byte[] { 1, 2, 3, 4 });
543+
BinaryFormatter formatter = new BinaryFormatter();
544+
545+
using (MemoryStream stream = new MemoryStream())
546+
{
547+
formatter.Serialize(stream, tuple);
548+
549+
stream.Position = 0;
550+
551+
Tuple<IComparable, object> deserialized = (Tuple<IComparable, object>)formatter.Deserialize(stream);
552+
Assert.Equal(tuple.Item1, deserialized.Item1);
553+
Assert.Equal(tuple.Item2, deserialized.Item2);
554+
}
555+
}
556+
538557
private static void ValidateEqualityComparer(object obj)
539558
{
540559
Type objType = obj.GetType();

0 commit comments

Comments
 (0)