From 5c8e7e33f8667eb4fccf318ae83bfad0f7ad2ef4 Mon Sep 17 00:00:00 2001 From: Martin Strecker <103252490+martin-strecker-sonarsource@users.noreply.github.com> Date: Tue, 28 Feb 2023 15:28:51 +0100 Subject: [PATCH] Old SE: Handle unsupported syntax gracefully (#6768) --- .../Sonar/SonarExplodedGraph.cs | 4 ++- .../CFG/Sonar/SonarControlFlowGraphTest.cs | 16 ++++++++++++ .../Sonar/SonarExplodedGraphTest.cs | 22 +++++++++++++++- .../Sonar/NullPointerDereference.CSharp11.cs | 25 +++++++++++++++++++ 4 files changed, 65 insertions(+), 2 deletions(-) diff --git a/analyzers/src/SonarAnalyzer.CSharp/SymbolicExecution/Sonar/SonarExplodedGraph.cs b/analyzers/src/SonarAnalyzer.CSharp/SymbolicExecution/Sonar/SonarExplodedGraph.cs index 50ff53fd26a..d677065704e 100644 --- a/analyzers/src/SonarAnalyzer.CSharp/SymbolicExecution/Sonar/SonarExplodedGraph.cs +++ b/analyzers/src/SonarAnalyzer.CSharp/SymbolicExecution/Sonar/SonarExplodedGraph.cs @@ -577,7 +577,9 @@ protected override void VisitInstruction(ExplodedGraphNode node) break; default: - throw new NotSupportedException($"{instruction.Kind()}"); + // Not Supported + // Do nothing + break; } newProgramState = InvokeChecks(newProgramState, (ps, check) => check.PostProcessInstruction(node.ProgramPoint, ps)); diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/CFG/Sonar/SonarControlFlowGraphTest.cs b/analyzers/tests/SonarAnalyzer.UnitTest/CFG/Sonar/SonarControlFlowGraphTest.cs index a10a3d0447e..10db0c26c67 100644 --- a/analyzers/tests/SonarAnalyzer.UnitTest/CFG/Sonar/SonarControlFlowGraphTest.cs +++ b/analyzers/tests/SonarAnalyzer.UnitTest/CFG/Sonar/SonarControlFlowGraphTest.cs @@ -4141,6 +4141,22 @@ public void Cfg_OrPattern_InIf_IsNotSupported() exception.Message.Should().Be("OrPattern"); } + [TestMethod] + public void Cfg_ParenthesizedPattern_InIf_IsNotSupported() + { + var exception = Assert.ThrowsException(() => Build(@"if (tainted is (string s)) { }")); + + exception.Message.Should().Be("ParenthesizedPattern"); + } + + [TestMethod] + public void Cfg_ListPattern_InIf_IsNotSupported() + { + var exception = Assert.ThrowsException(() => Build(@"if (tainted is []) { }")); + + exception.Message.Should().Be("ListPattern"); + } + [TestMethod] public void Cfg_Switch_Patterns_NoDefault() { diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/SymbolicExecution/Sonar/SonarExplodedGraphTest.cs b/analyzers/tests/SonarAnalyzer.UnitTest/SymbolicExecution/Sonar/SonarExplodedGraphTest.cs index e3bb80b6cb0..4ab0ad9c7a6 100644 --- a/analyzers/tests/SonarAnalyzer.UnitTest/SymbolicExecution/Sonar/SonarExplodedGraphTest.cs +++ b/analyzers/tests/SonarAnalyzer.UnitTest/SymbolicExecution/Sonar/SonarExplodedGraphTest.cs @@ -28,7 +28,6 @@ using SonarAnalyzer.LiveVariableAnalysis.CSharp; using SonarAnalyzer.SymbolicExecution.Constraints; using SonarAnalyzer.SymbolicExecution.Sonar; -using SonarAnalyzer.SymbolicExecution.Sonar.Constraints; using SonarAnalyzer.UnitTest.CFG.Sonar; using SonarAnalyzer.UnitTest.Helpers; @@ -901,6 +900,27 @@ public void ExplodedGraph_IsPattern_WithPositionalPattern() context.WalkWithInstructions(4); } + [DataTestMethod] + [DataRow("int")] + [DataRow("(string s)")] + [DataRow("1 or 2")] + [DataRow("1 and 2")] + [DataRow("not 1")] + [DataRow("> 5")] + [DataRow("[] empty")] + public void ExplodedGraph_SwitchStatement_UnsupportedPatternKinds(string pattern) + { + var testInput = $$""" + switch (new object()) + { + case {{pattern}}: break; + } + """; + var context = new ExplodedGraphContext(testInput); + var walk = () => context.WalkWithInstructions(2); + walk.Should().Throw().WithMessage("Expected NumberOfExitBlockReached to be 1, but found 0."); + } + [TestMethod] public void ExplodedGraph_SwitchExpressionVisit() { diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Sonar/NullPointerDereference.CSharp11.cs b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Sonar/NullPointerDereference.CSharp11.cs index c6f4e7e4528..9d0bf1f6501 100644 --- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Sonar/NullPointerDereference.CSharp11.cs +++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SymbolicExecution/Sonar/NullPointerDereference.CSharp11.cs @@ -19,4 +19,29 @@ public void ListPattern(object[] objects) } } } + + // https://github.com/SonarSource/sonar-dotnet/issues/6766 + public class Repo_6766 + { + public void SwitchCasePattern(object o, object[] array) + { + switch (o) + { + case (1 or 2): // Parenthesized + case 3 or 4: // Binary + case > 5: // Relational + case char: // Type + case Exception { Message.Length: 1 }: // Recursive + case (int _, int _): // Recursive + case not "": // Unary + break; + } + switch (array) + { + case []: // list pattern + case [1, .., 2]: // list pattern with slice + break; + } + } + } }