Skip to content

Commit 51dd600

Browse files
committed
PropertySetAnalysis: Handling assignments to flow captures when tracking properties
1 parent 5b922ab commit 51dd600

2 files changed

Lines changed: 43 additions & 18 deletions

File tree

src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotUseInsecureDeserializerBinaryFormatterWithoutBinderTests.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,7 +1198,7 @@ public BookRecord DeserializeBookRecord(byte[] bytes)
11981198
}
11991199

12001200
[Fact]
1201-
public void Deserialize_SharedBinderInstance_Diagnostic()
1201+
public void Deserialize_SharedBinderInstance_NoDiagnostic()
12021202
{
12031203
VerifyCSharpWithMyBinderDefined(@"
12041204
using System;
@@ -1220,10 +1220,7 @@ private object DoDeserialization(Stream stream)
12201220
return f.Deserialize(stream);
12211221
}
12221222
}
1223-
}",
1224-
GetCSharpResultAt(18, 20, BinderNotSetRule, "object BinaryFormatter.Deserialize(Stream serializationStream)"));
1225-
1226-
// Ideally, we'd be able to tell f.Binder is non-null.
1223+
}");
12271224
}
12281225

12291226
[Fact]

src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysis.PropertySetDataFlowOperationVisitor.cs

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -241,19 +241,9 @@ protected override PropertySetAbstractValue VisitAssignmentOperation(IAssignment
241241
AnalysisEntity targetAnalysisEntity = null;
242242
if (operation.Target.Kind == OperationKind.FlowCaptureReference)
243243
{
244-
PointsToAbstractValue lValuePointsToAbstractValue = this.GetPointsToAbstractValue(operation.Target);
245-
if (lValuePointsToAbstractValue.LValueCapturedOperations.Count == 1)
244+
if (this.TryUnwrapFlowCaptureReference(operation.Target, out IOperation lValueOperation, OperationKind.PropertyReference, OperationKind.FieldReference))
246245
{
247-
IOperation lValueOperation = lValuePointsToAbstractValue.LValueCapturedOperations.First();
248-
if (lValueOperation.Kind == OperationKind.FieldReference
249-
|| lValueOperation.Kind == OperationKind.PropertyReference)
250-
{
251-
this.AnalysisEntityFactory.TryCreate(lValueOperation, out targetAnalysisEntity);
252-
}
253-
}
254-
else
255-
{
256-
Debug.Fail("Can LValues FlowCaptureReferences have more than one operation?");
246+
this.AnalysisEntityFactory.TryCreate(lValueOperation, out targetAnalysisEntity);
257247
}
258248
}
259249
else
@@ -295,7 +285,14 @@ protected override PropertySetAbstractValue VisitAssignmentOperation(IAssignment
295285
}
296286
}
297287

298-
if (operation.Target is IPropertyReferenceOperation propertyReferenceOperation
288+
IPropertyReferenceOperation propertyReferenceOperation = operation.Target as IPropertyReferenceOperation;
289+
if (propertyReferenceOperation == null && operation.Target.Kind == OperationKind.FlowCaptureReference)
290+
{
291+
this.TryUnwrapFlowCaptureReference(operation.Target, out IOperation lValue, OperationKind.PropertyReference);
292+
propertyReferenceOperation = lValue as IPropertyReferenceOperation;
293+
}
294+
295+
if (propertyReferenceOperation != null
299296
&& propertyReferenceOperation.Instance != null
300297
&& this.TrackedTypeSymbols.Any(s => propertyReferenceOperation.Instance.Type.GetBaseTypesAndThis().Contains(s))
301298
&& this.DataFlowAnalysisContext.PropertyMappers.TryGetPropertyMapper(
@@ -698,6 +695,37 @@ private void MergeInterproceduralResults(IOperation originalOperation)
698695
this._visitedLambdas.Add(lambdaOperation);
699696
}
700697
}
698+
699+
/// <summary>
700+
/// Attempts to find the underlying IOperation that a flow capture reference refers to.
701+
/// </summary>
702+
/// <param name="flowCaptureReferenceOperation">Operation that may be a flow capture reference to look at.</param>
703+
/// <param name="unwrappedOperation">The found underlying operation, if any.</param>
704+
/// <param name="kinds">Kinds of operations to look for.</param>
705+
/// <returns>True if found, false otherwise.</returns>
706+
private bool TryUnwrapFlowCaptureReference(IOperation flowCaptureReferenceOperation, out IOperation unwrappedOperation, params OperationKind[] kinds)
707+
{
708+
unwrappedOperation = null;
709+
if (flowCaptureReferenceOperation != null && flowCaptureReferenceOperation.Kind == OperationKind.FlowCaptureReference)
710+
{
711+
PointsToAbstractValue lValuePointsToAbstractValue = this.GetPointsToAbstractValue(flowCaptureReferenceOperation);
712+
if (lValuePointsToAbstractValue.LValueCapturedOperations.Count == 1)
713+
{
714+
IOperation lValueOperation = lValuePointsToAbstractValue.LValueCapturedOperations.First();
715+
if (kinds == null || kinds.Contains(lValueOperation.Kind))
716+
{
717+
unwrappedOperation = lValueOperation;
718+
return true;
719+
}
720+
}
721+
else
722+
{
723+
Debug.Fail("Can LValues FlowCaptureReferences have more than one operation?");
724+
}
725+
}
726+
727+
return false;
728+
}
701729
}
702730
}
703731
}

0 commit comments

Comments
 (0)