Skip to content

Commit 7ab2011

Browse files
Adam Sitnikcarlossanlop
Adam Sitnik
authored andcommitted
Bypassing Serialization Binders with BinaryFormatter Mutation
1 parent d246d8e commit 7ab2011

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
@@ -367,7 +367,7 @@ private void WriteMembers(NameInfo memberNameInfo,
367367
return;
368368
}
369369

370-
if (!WriteKnownValueClass(memberNameInfo, memberTypeNameInfo, memberData!))
370+
if (!WriteKnownValueClass(memberNameInfo, memberTypeNameInfo, memberData!, ref assignUniqueIdToValueType))
371371
{
372372
if (outType == null)
373373
{
@@ -616,10 +616,10 @@ private void WriteArrayMember(WriteObjectInfo objectInfo, NameInfo arrayElemType
616616
actualTypeInfo._isArrayItem = true;
617617
}
618618

619-
if (!WriteKnownValueClass(arrayElemTypeNameInfo, actualTypeInfo, data!))
619+
bool assignUniqueIdForValueTypes = false;
620+
if (!WriteKnownValueClass(arrayElemTypeNameInfo, actualTypeInfo, data!, ref assignUniqueIdForValueTypes))
620621
{
621622
object obj = data!;
622-
bool assignUniqueIdForValueTypes = false;
623623
if (ReferenceEquals(arrayElemTypeNameInfo._type, Converter.s_typeofObject))
624624
{
625625
assignUniqueIdForValueTypes = true;
@@ -799,11 +799,12 @@ private long Schedule(object obj, bool assignUniqueIdToValueType, Type? type, Wr
799799
}
800800

801801
// Determines if a type is a primitive type, if it is it is written
802-
private bool WriteKnownValueClass(NameInfo memberNameInfo, NameInfo typeNameInfo, object data)
802+
private bool WriteKnownValueClass(NameInfo memberNameInfo, NameInfo typeNameInfo, object data, ref bool assignUniqueIdToValueType)
803803
{
804804
if (ReferenceEquals(typeNameInfo._type, Converter.s_typeofString))
805805
{
806806
WriteString(memberNameInfo, typeNameInfo, data);
807+
return true;
807808
}
808809
else
809810
{
@@ -817,18 +818,22 @@ private bool WriteKnownValueClass(NameInfo memberNameInfo, NameInfo typeNameInfo
817818
if (typeNameInfo._isArray) // null if an array
818819
{
819820
_serWriter.WriteItem(memberNameInfo, typeNameInfo, data);
821+
return true;
820822
}
821-
else
823+
else if (memberNameInfo._type == typeNameInfo._type
824+
|| memberNameInfo._type == typeof(object)
825+
|| (memberNameInfo._type != null && Nullable.GetUnderlyingType(memberNameInfo._type) != null))
822826
{
823827
_serWriter.WriteMember(memberNameInfo, typeNameInfo, data);
828+
return true;
824829
}
825830
}
826831
}
827832

828-
return true;
833+
assignUniqueIdToValueType = true;
834+
return false;
829835
}
830836

831-
832837
// Writes an object reference to the stream.
833838
private void WriteObjectRef(NameInfo nameInfo, long objectId) =>
834839
_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
@@ -536,6 +536,25 @@ public void Roundtrip_ArrayContainingArrayAtNonZeroLowerBound()
536536
BinaryFormatterHelpers.Clone(Array.CreateInstance(typeof(uint[]), new[] { 5 }, new[] { 1 }));
537537
}
538538

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

0 commit comments

Comments
 (0)