Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 83fb328

Browse files
committed
C#: Move NonReturning module into own file
1 parent 64539b0 commit 83fb328

2 files changed

Lines changed: 141 additions & 139 deletions

File tree

csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowGraph.qll

Lines changed: 1 addition & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,7 @@ module ControlFlow {
820820
*/
821821
private module Successor {
822822
private import semmle.code.csharp.ExprOrStmtParent
823+
private import semmle.code.csharp.controlflow.internal.NonReturning
823824

824825
/**
825826
* A control flow element where the children are evaluated following a
@@ -1730,145 +1731,6 @@ module ControlFlow {
17301731
)
17311732
}
17321733

1733-
/**
1734-
* Provides a simple analysis for identifying calls to callables that will
1735-
* not return.
1736-
*/
1737-
private module NonReturning {
1738-
private import semmle.code.csharp.ExprOrStmtParent
1739-
private import semmle.code.csharp.commons.Assertions
1740-
private import semmle.code.csharp.frameworks.System
1741-
1742-
/** A call that definitely does not return (conservative analysis). */
1743-
abstract class NonReturningCall extends Call {
1744-
/** Gets a valid completion for this non-returning call. */
1745-
abstract Completion getACompletion();
1746-
}
1747-
1748-
private class ExitingCall extends NonReturningCall {
1749-
ExitingCall() {
1750-
this.getTarget() instanceof ExitingCallable
1751-
or
1752-
exists(AssertMethod m | m = this.(FailingAssertion).getAssertMethod() |
1753-
not exists(m.getExceptionClass())
1754-
)
1755-
}
1756-
1757-
override ExitCompletion getACompletion() { any() }
1758-
}
1759-
1760-
private class ThrowingCall extends NonReturningCall {
1761-
private ThrowCompletion c;
1762-
1763-
ThrowingCall() {
1764-
c = this.getTarget().(ThrowingCallable).getACallCompletion()
1765-
or
1766-
exists(AssertMethod m | m = this.(FailingAssertion).getAssertMethod() |
1767-
c.getExceptionClass() = m.getExceptionClass()
1768-
)
1769-
}
1770-
1771-
override ThrowCompletion getACompletion() { result = c }
1772-
}
1773-
1774-
abstract private class NonReturningCallable extends Callable {
1775-
NonReturningCallable() {
1776-
not exists(ReturnStmt ret | ret.getEnclosingCallable() = this) and
1777-
not hasAccessorAutoImplementation(this, _) and
1778-
not exists(Virtualizable v | v.isOverridableOrImplementable() |
1779-
v = this or
1780-
v = this.(Accessor).getDeclaration()
1781-
)
1782-
}
1783-
}
1784-
1785-
abstract private class ExitingCallable extends NonReturningCallable { }
1786-
1787-
private class DirectlyExitingCallable extends ExitingCallable {
1788-
DirectlyExitingCallable() {
1789-
this = any(Method m |
1790-
m.hasQualifiedName("System.Environment", "Exit") or
1791-
m.hasQualifiedName("System.Windows.Forms.Application", "Exit")
1792-
)
1793-
}
1794-
}
1795-
1796-
private class IndirectlyExitingCallable extends ExitingCallable {
1797-
IndirectlyExitingCallable() {
1798-
forex(ControlFlowElement body | body = this.getABody() | body = getAnExitingElement())
1799-
}
1800-
}
1801-
1802-
private ControlFlowElement getAnExitingElement() {
1803-
result instanceof ExitingCall
1804-
or
1805-
result = getAnExitingStmt()
1806-
}
1807-
1808-
private Stmt getAnExitingStmt() {
1809-
result.(ExprStmt).getExpr() = getAnExitingElement()
1810-
or
1811-
result.(BlockStmt).getFirstStmt() = getAnExitingElement()
1812-
or
1813-
exists(IfStmt ifStmt |
1814-
result = ifStmt and
1815-
ifStmt.getThen() = getAnExitingElement() and
1816-
ifStmt.getElse() = getAnExitingElement()
1817-
)
1818-
}
1819-
1820-
private class ThrowingCallable extends NonReturningCallable {
1821-
ThrowingCallable() {
1822-
forex(ControlFlowElement body | body = this.getABody() | body = getAThrowingElement(_))
1823-
}
1824-
1825-
/** Gets a valid completion for a call to this throwing callable. */
1826-
ThrowCompletion getACallCompletion() { this.getABody() = getAThrowingElement(result) }
1827-
}
1828-
1829-
private predicate directlyThrows(ThrowElement te, ThrowCompletion c) {
1830-
c.getExceptionClass() = te.getThrownExceptionType() and
1831-
// For stub implementations, there may exist proper implementations that are not seen
1832-
// during compilation, so we conservatively rule those out
1833-
not isStub(te)
1834-
}
1835-
1836-
private ControlFlowElement getAThrowingElement(ThrowCompletion c) {
1837-
c = result.(ThrowingCall).getACompletion()
1838-
or
1839-
directlyThrows(result, c)
1840-
or
1841-
result = getAThrowingStmt(c)
1842-
}
1843-
1844-
private Stmt getAThrowingStmt(ThrowCompletion c) {
1845-
directlyThrows(result, c)
1846-
or
1847-
result.(ExprStmt).getExpr() = getAThrowingElement(c)
1848-
or
1849-
result.(BlockStmt).getFirstStmt() = getAThrowingStmt(c)
1850-
or
1851-
exists(IfStmt ifStmt, ThrowCompletion c1, ThrowCompletion c2 |
1852-
result = ifStmt and
1853-
ifStmt.getThen() = getAThrowingStmt(c1) and
1854-
ifStmt.getElse() = getAThrowingStmt(c2)
1855-
|
1856-
c = c1
1857-
or
1858-
c = c2
1859-
)
1860-
}
1861-
1862-
/** Holds if `throw` element `te` indicates a stub implementation. */
1863-
private predicate isStub(ThrowElement te) {
1864-
exists(Expr e | e = te.getExpr() |
1865-
e instanceof NullLiteral or
1866-
e.getType() instanceof SystemNotImplementedExceptionClass
1867-
)
1868-
}
1869-
}
1870-
private import NonReturning
1871-
18721734
/**
18731735
* Gets a control flow successor for control flow element `cfe`, given that
18741736
* `cfe` finishes with completion `c`.
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/**
2+
* INTERNAL: Do not use.
3+
*
4+
* Provides a simple analysis for identifying calls to callables that will
5+
* not return.
6+
*/
7+
8+
import csharp
9+
private import semmle.code.csharp.ExprOrStmtParent
10+
private import semmle.code.csharp.commons.Assertions
11+
private import semmle.code.csharp.frameworks.System
12+
private import semmle.code.csharp.controlflow.internal.Completion
13+
14+
/** A call that definitely does not return (conservative analysis). */
15+
abstract class NonReturningCall extends Call {
16+
/** Gets a valid completion for this non-returning call. */
17+
abstract Completion getACompletion();
18+
}
19+
20+
private class ExitingCall extends NonReturningCall {
21+
ExitingCall() {
22+
this.getTarget() instanceof ExitingCallable
23+
or
24+
exists(AssertMethod m | m = this.(FailingAssertion).getAssertMethod() |
25+
not exists(m.getExceptionClass())
26+
)
27+
}
28+
29+
override ExitCompletion getACompletion() { any() }
30+
}
31+
32+
private class ThrowingCall extends NonReturningCall {
33+
private ThrowCompletion c;
34+
35+
ThrowingCall() {
36+
c = this.getTarget().(ThrowingCallable).getACallCompletion()
37+
or
38+
exists(AssertMethod m | m = this.(FailingAssertion).getAssertMethod() |
39+
c.getExceptionClass() = m.getExceptionClass()
40+
)
41+
}
42+
43+
override ThrowCompletion getACompletion() { result = c }
44+
}
45+
46+
abstract private class NonReturningCallable extends Callable {
47+
NonReturningCallable() {
48+
not exists(ReturnStmt ret | ret.getEnclosingCallable() = this) and
49+
not hasAccessorAutoImplementation(this, _) and
50+
not exists(Virtualizable v | v.isOverridableOrImplementable() |
51+
v = this or
52+
v = this.(Accessor).getDeclaration()
53+
)
54+
}
55+
}
56+
57+
abstract private class ExitingCallable extends NonReturningCallable { }
58+
59+
private class DirectlyExitingCallable extends ExitingCallable {
60+
DirectlyExitingCallable() {
61+
this = any(Method m |
62+
m.hasQualifiedName("System.Environment", "Exit") or
63+
m.hasQualifiedName("System.Windows.Forms.Application", "Exit")
64+
)
65+
}
66+
}
67+
68+
private class IndirectlyExitingCallable extends ExitingCallable {
69+
IndirectlyExitingCallable() {
70+
forex(ControlFlowElement body | body = this.getABody() | body = getAnExitingElement())
71+
}
72+
}
73+
74+
private ControlFlowElement getAnExitingElement() {
75+
result instanceof ExitingCall
76+
or
77+
result = getAnExitingStmt()
78+
}
79+
80+
private Stmt getAnExitingStmt() {
81+
result.(ExprStmt).getExpr() = getAnExitingElement()
82+
or
83+
result.(BlockStmt).getFirstStmt() = getAnExitingElement()
84+
or
85+
exists(IfStmt ifStmt |
86+
result = ifStmt and
87+
ifStmt.getThen() = getAnExitingElement() and
88+
ifStmt.getElse() = getAnExitingElement()
89+
)
90+
}
91+
92+
private class ThrowingCallable extends NonReturningCallable {
93+
ThrowingCallable() {
94+
forex(ControlFlowElement body | body = this.getABody() | body = getAThrowingElement(_))
95+
}
96+
97+
/** Gets a valid completion for a call to this throwing callable. */
98+
ThrowCompletion getACallCompletion() { this.getABody() = getAThrowingElement(result) }
99+
}
100+
101+
private predicate directlyThrows(ThrowElement te, ThrowCompletion c) {
102+
c.getExceptionClass() = te.getThrownExceptionType() and
103+
// For stub implementations, there may exist proper implementations that are not seen
104+
// during compilation, so we conservatively rule those out
105+
not isStub(te)
106+
}
107+
108+
private ControlFlowElement getAThrowingElement(ThrowCompletion c) {
109+
c = result.(ThrowingCall).getACompletion()
110+
or
111+
directlyThrows(result, c)
112+
or
113+
result = getAThrowingStmt(c)
114+
}
115+
116+
private Stmt getAThrowingStmt(ThrowCompletion c) {
117+
directlyThrows(result, c)
118+
or
119+
result.(ExprStmt).getExpr() = getAThrowingElement(c)
120+
or
121+
result.(BlockStmt).getFirstStmt() = getAThrowingStmt(c)
122+
or
123+
exists(IfStmt ifStmt, ThrowCompletion c1, ThrowCompletion c2 |
124+
result = ifStmt and
125+
ifStmt.getThen() = getAThrowingStmt(c1) and
126+
ifStmt.getElse() = getAThrowingStmt(c2)
127+
|
128+
c = c1
129+
or
130+
c = c2
131+
)
132+
}
133+
134+
/** Holds if `throw` element `te` indicates a stub implementation. */
135+
private predicate isStub(ThrowElement te) {
136+
exists(Expr e | e = te.getExpr() |
137+
e instanceof NullLiteral or
138+
e.getType() instanceof SystemNotImplementedExceptionClass
139+
)
140+
}

0 commit comments

Comments
 (0)