Skip to content

Commit

Permalink
C# 7.x pattern matching switch support added
Browse files Browse the repository at this point in the history
  • Loading branch information
JarLob committed Jul 24, 2019
1 parent 52ba500 commit 728abed
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 4 deletions.
60 changes: 60 additions & 0 deletions SecurityCodeScan.Test/Tests/Taint/TaintAnalyzerControlFlowTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,66 @@ public void Foo(object o)
await VerifyCSharpDiagnostic(cSharpTest).ConfigureAwait(false);
}

[TestCategory("Detect")]
[TestMethod]
public async Task PatternMatchingSwitch()
{
var cSharpTest = @"
using System;
using System.Data.SqlClient;
using System.Web.Mvc;
namespace sample
{
class Test : Controller
{
public void Foo(object o)
{
switch(o)
{
case String s:
new SqlCommand(s);
break;
}
}
}
}
";

await VerifyCSharpDiagnostic(cSharpTest, Expected).ConfigureAwait(false);
}

[TestCategory("Detect")]
[TestMethod]
public async Task PatternMatchingSwitch2()
{
var cSharpTest = @"
using System;
using System.Data.SqlClient;
using System.Web.Mvc;
namespace sample
{
class Test : Controller
{
public void Foo(object o)
{
string x = null;
switch(o)
{
case String s:
x = s;
break;
}
new SqlCommand(x);
}
}
}
";

await VerifyCSharpDiagnostic(cSharpTest, Expected).ConfigureAwait(false);
}

[TestCategory("Safe")]
[TestMethod]
public async Task Cast()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,6 @@ private VariableState VisitNode(SyntaxNode node, ExecutionState state)
return VisitNode(elseClauseSyntax.Statement, state);
case SwitchStatementSyntax switchStatementSyntax:
return VisitSwitch(switchStatementSyntax, state);
case SwitchSectionSyntax switchSectionSyntax:
return VisitStatements(switchSectionSyntax.Statements, state, new VariableState(node, VariableTaint.Unset));
}

foreach (var n in node.ChildNodes())
Expand Down Expand Up @@ -225,21 +223,44 @@ private VariableState VisitFromClause(FromClauseSyntax fromClauseSyntax, Executi
return fromClauseState;
}

private VariableState VisitSwitchSection(SwitchSectionSyntax switchSectionSyntax, ExecutionState state, VariableState switchStatementVarState)
{
if (switchSectionSyntax.Labels.Any(x => x is CasePatternSwitchLabelSyntax))
{
var caseState = new ExecutionState(state);
foreach (var switchLabelSyntax in switchSectionSyntax.Labels)
{
if (switchLabelSyntax is CasePatternSwitchLabelSyntax casePatternSwitchLabel &&
casePatternSwitchLabel.Pattern is DeclarationPatternSyntax declarationPattern &&
declarationPattern.Designation is SingleVariableDesignationSyntax singleVariableDesignation)
{
caseState.AddNewValue(ResolveIdentifier(singleVariableDesignation.Identifier), switchStatementVarState);
}
}

var caseStateVariable = VisitStatements(switchSectionSyntax.Statements, caseState, new VariableState(switchSectionSyntax, VariableTaint.Unset));
state.Replace(caseState);
return caseStateVariable;
}

return VisitStatements(switchSectionSyntax.Statements, state, new VariableState(switchSectionSyntax, VariableTaint.Unset));
}

private VariableState VisitSwitch(SwitchStatementSyntax switchStatementSyntax, ExecutionState state)
{
var exprVarState = VisitExpression(switchStatementSyntax.Expression, state);
if (switchStatementSyntax.Sections.Count <= 0)
return exprVarState;

var firstCaseState = new ExecutionState(state);
var sectionVarState = VisitNode(switchStatementSyntax.Sections[0], firstCaseState);
var sectionVarState = VisitSwitchSection(switchStatementSyntax.Sections[0], firstCaseState, exprVarState);
exprVarState.MergeTaint(sectionVarState.Taint);

for (var i = 1; i < switchStatementSyntax.Sections.Count; i++)
{
var section = switchStatementSyntax.Sections[i];
var caseState = new ExecutionState(state);
sectionVarState = VisitNode(section, caseState);
sectionVarState = VisitSwitchSection(section, caseState, exprVarState);
exprVarState.MergeTaint(sectionVarState.Taint);
firstCaseState.Merge(caseState);
}
Expand Down

0 comments on commit 728abed

Please sign in to comment.