Skip to content

Commit b7484e6

Browse files
committed
C#: Recognize Code Contract assertions
1 parent 5429448 commit b7484e6

File tree

4 files changed

+82
-1
lines changed

4 files changed

+82
-1
lines changed

csharp/ql/src/semmle/code/csharp/commons/Assertions.qll

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/** Provides classes for assertions. */
22

33
private import semmle.code.csharp.frameworks.system.Diagnostics
4+
private import semmle.code.csharp.frameworks.system.diagnostics.Contracts
45
private import semmle.code.csharp.frameworks.test.VisualStudio
56
private import semmle.code.csharp.frameworks.System
67
private import ControlFlow
@@ -169,6 +170,29 @@ class SystemDiagnosticsDebugAssertTrueMethod extends AssertTrueMethod {
169170
}
170171
}
171172

173+
/**
174+
* A `System.Diagnostics.Contracts.Contract` assertion method.
175+
*/
176+
class SystemDiagnosticsContractAssertTrueMethod extends AssertTrueMethod {
177+
SystemDiagnosticsContractAssertTrueMethod() {
178+
exists(SystemDiagnosticsContractsContractClass c |
179+
this = c.getAnAssertMethod()
180+
or
181+
this = c.getAnAssumeMethod()
182+
or
183+
this = c.getARequiresMethod()
184+
)
185+
}
186+
187+
override int getAssertionIndex() { result = 0 }
188+
189+
override Class getExceptionClass() {
190+
// A failing assertion generates a message box, see
191+
// https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.contracts.contract.assert
192+
none()
193+
}
194+
}
195+
172196
/** A Visual Studio assertion method. */
173197
class VSTestAssertTrueMethod extends AssertTrueMethod {
174198
VSTestAssertTrueMethod() { this = any(VSTestAssertClass c).getIsTrueMethod() }

csharp/ql/src/semmle/code/csharp/frameworks/system/Diagnostics.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class SystemDiagnosticsDebugClass extends SystemDiagnosticsClass {
2323
this.isStatic()
2424
}
2525

26-
/** Gets and `Assert(bool, ...)` method. */
26+
/** Gets an `Assert(bool, ...)` method. */
2727
Method getAssertMethod() {
2828
result.getDeclaringType() = this and
2929
result.hasName("Assert") and
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/** Provides definitions related to the namespace `System.Diagnostics.Contracts`. */
2+
3+
import semmle.code.csharp.Type
4+
private import semmle.code.csharp.frameworks.system.Diagnostics
5+
6+
/** The `System.Diagnostics.Contracts` namespace. */
7+
class SystemDiagnosticsContractsNamespace extends Namespace {
8+
SystemDiagnosticsContractsNamespace() {
9+
this.getParentNamespace() instanceof SystemDiagnosticsNamespace and
10+
this.hasName("Contracts")
11+
}
12+
}
13+
14+
/** A class in the `System.Diagnostics.Contracts` namespace. */
15+
class SystemDiagnosticsContractsClass extends Class {
16+
SystemDiagnosticsContractsClass() { this.getNamespace() instanceof SystemDiagnosticsContractsNamespace }
17+
}
18+
19+
/** The `System.Diagnostics.Contracts.Contract` class. */
20+
class SystemDiagnosticsContractsContractClass extends SystemDiagnosticsContractsClass {
21+
SystemDiagnosticsContractsContractClass() {
22+
this.hasName("Contract") and
23+
this.isStatic()
24+
}
25+
26+
/** Gets an `Assert(bool, ...)` method. */
27+
Method getAnAssertMethod() {
28+
result.getDeclaringType() = this and
29+
result.hasName("Assert") and
30+
result.getParameter(0).getType() instanceof BoolType and
31+
result.getReturnType() instanceof VoidType
32+
}
33+
34+
/** Gets an `Assume(bool, ...)` method. */
35+
Method getAnAssumeMethod() {
36+
result.getDeclaringType() = this and
37+
result.hasName("Assume") and
38+
result.getParameter(0).getType() instanceof BoolType and
39+
result.getReturnType() instanceof VoidType
40+
}
41+
42+
/** Gets a `Requires(bool, ...)` method. */
43+
Method getARequiresMethod() {
44+
result.getDeclaringType() = this and
45+
result.hasName("Requires") and
46+
result.getParameter(0).getType() instanceof BoolType and
47+
result.getReturnType() instanceof VoidType
48+
}
49+
}

csharp/ql/test/library-tests/commons/Assertions/Assertions.expected

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ assertTrue
1414
| Assertions.cs:37:9:37:33 | call to method MyAssert | Assertions.cs:37:29:37:32 | true |
1515
| Assertions.cs:38:9:38:35 | call to method MyAssert2 | Assertions.cs:38:30:38:34 | false |
1616
| Assertions.cs:39:9:39:34 | call to method MyAssert2 | Assertions.cs:39:30:39:33 | true |
17+
| Assertions.cs:44:9:44:36 | call to method Requires | Assertions.cs:44:27:44:35 | ... != ... |
18+
| Assertions.cs:45:9:45:58 | call to method Requires | Assertions.cs:45:27:45:35 | ... != ... |
19+
| Assertions.cs:46:9:46:47 | call to method Requires | Assertions.cs:46:38:46:46 | ... != ... |
20+
| Assertions.cs:47:9:47:69 | call to method Requires | Assertions.cs:47:38:47:46 | ... != ... |
21+
| Assertions.cs:48:9:48:34 | call to method Assert | Assertions.cs:48:25:48:33 | ... != ... |
22+
| Assertions.cs:49:9:49:51 | call to method Assert | Assertions.cs:49:25:49:33 | ... != ... |
23+
| Assertions.cs:50:9:50:34 | call to method Assume | Assertions.cs:50:25:50:33 | ... != ... |
24+
| Assertions.cs:51:9:51:51 | call to method Assume | Assertions.cs:51:25:51:33 | ... != ... |
1725
assertFalse
1826
| Assertions.cs:22:9:22:33 | call to method IsFalse | Assertions.cs:22:24:22:32 | ... != ... |
1927
| Assertions.cs:23:9:23:33 | call to method IsFalse | Assertions.cs:23:24:23:32 | ... == ... |

0 commit comments

Comments
 (0)