-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #17763 from geoffw0/cfgcount3
Rust: Count number of CFG inconsistencies
- Loading branch information
Showing
8 changed files
with
145 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,37 +1,8 @@ | ||
import rust | ||
import codeql.rust.controlflow.internal.ControlFlowGraphImpl::Consistency as Consistency | ||
import Consistency | ||
import codeql.rust.controlflow.ControlFlowGraph | ||
import codeql.rust.controlflow.internal.ControlFlowGraphImpl as CfgImpl | ||
import codeql.rust.controlflow.internal.Completion | ||
|
||
/** | ||
* All `Expr` nodes are `PostOrderTree`s | ||
* @name Control flow graph inconsistencies | ||
* @description Lists the control flow graph inconsistencies in the database. This query is intended for internal use. | ||
* @kind table | ||
* @id rust/diagnostics/cfg-consistency | ||
*/ | ||
query predicate nonPostOrderExpr(Expr e, string cls) { | ||
cls = e.getPrimaryQlClasses() and | ||
not e instanceof LetExpr and | ||
not e instanceof ParenExpr and | ||
exists(AstNode last, Completion c | | ||
CfgImpl::last(e, last, c) and | ||
last != e and | ||
c instanceof NormalCompletion | ||
) | ||
} | ||
|
||
query predicate scopeNoFirst(CfgScope scope) { | ||
Consistency::scopeNoFirst(scope) and | ||
not scope = any(Function f | not exists(f.getBody())) and | ||
not scope = any(ClosureExpr c | not exists(c.getBody())) | ||
} | ||
|
||
/** Holds if `be` is the `else` branch of a `let` statement that results in a panic. */ | ||
private predicate letElsePanic(BlockExpr be) { | ||
be = any(LetStmt let).getLetElse().getBlockExpr() and | ||
exists(Completion c | CfgImpl::last(be, _, c) | completionIsNormal(c)) | ||
} | ||
|
||
query predicate deadEnd(CfgImpl::Node node) { | ||
Consistency::deadEnd(node) and | ||
not letElsePanic(node.getAstNode()) | ||
} | ||
import codeql.rust.controlflow.internal.CfgConsistency |
94 changes: 94 additions & 0 deletions
94
rust/ql/lib/codeql/rust/controlflow/internal/CfgConsistency.qll
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/** | ||
* Provides classes for recognizing control flow graph inconsistencies. | ||
*/ | ||
|
||
private import rust | ||
private import codeql.rust.controlflow.internal.ControlFlowGraphImpl::Consistency as Consistency | ||
import Consistency | ||
private import codeql.rust.controlflow.ControlFlowGraph | ||
private import codeql.rust.controlflow.internal.ControlFlowGraphImpl as CfgImpl | ||
private import codeql.rust.controlflow.internal.Completion | ||
|
||
/** | ||
* All `Expr` nodes are `PostOrderTree`s | ||
*/ | ||
query predicate nonPostOrderExpr(Expr e, string cls) { | ||
cls = e.getPrimaryQlClasses() and | ||
not e instanceof LetExpr and | ||
not e instanceof ParenExpr and | ||
exists(AstNode last, Completion c | | ||
CfgImpl::last(e, last, c) and | ||
last != e and | ||
c instanceof NormalCompletion | ||
) | ||
} | ||
|
||
/** | ||
* Holds if CFG scope `scope` lacks an initial AST node. Overrides shared consistency predicate. | ||
*/ | ||
query predicate scopeNoFirst(CfgScope scope) { | ||
Consistency::scopeNoFirst(scope) and | ||
not scope = any(Function f | not exists(f.getBody())) and | ||
not scope = any(ClosureExpr c | not exists(c.getBody())) | ||
} | ||
|
||
/** Holds if `be` is the `else` branch of a `let` statement that results in a panic. */ | ||
private predicate letElsePanic(BlockExpr be) { | ||
be = any(LetStmt let).getLetElse().getBlockExpr() and | ||
exists(Completion c | CfgImpl::last(be, _, c) | completionIsNormal(c)) | ||
} | ||
|
||
/** | ||
* Holds if `node` is lacking a successor. Overrides shared consistency predicate. | ||
*/ | ||
query predicate deadEnd(CfgImpl::Node node) { | ||
Consistency::deadEnd(node) and | ||
not letElsePanic(node.getAstNode()) | ||
} | ||
|
||
/** | ||
* Gets counts of control flow graph inconsistencies of each type. | ||
*/ | ||
int getCfgInconsistencyCounts(string type) { | ||
// total results from all the CFG consistency query predicates in: | ||
// - `codeql.rust.controlflow.internal.CfgConsistency` (this file) | ||
// - `shared.controlflow.codeql.controlflow.Cfg` | ||
type = "Non-unique set representation" and | ||
result = count(CfgImpl::Splits ss | nonUniqueSetRepresentation(ss, _) | ss) | ||
or | ||
type = "Splitting invariant 2" and | ||
result = count(AstNode n | breakInvariant2(n, _, _, _, _, _) | n) | ||
or | ||
type = "Splitting invariant 3" and | ||
result = count(AstNode n | breakInvariant3(n, _, _, _, _, _) | n) | ||
or | ||
type = "Splitting invariant 4" and | ||
result = count(AstNode n | breakInvariant4(n, _, _, _, _, _) | n) | ||
or | ||
type = "Splitting invariant 5" and | ||
result = count(AstNode n | breakInvariant5(n, _, _, _, _, _) | n) | ||
or | ||
type = "Multiple successors of the same type" and | ||
result = count(CfgNode n | multipleSuccessors(n, _, _) | n) | ||
or | ||
type = "Simple and normal successors" and | ||
result = count(CfgNode n | simpleAndNormalSuccessors(n, _, _, _, _) | n) | ||
or | ||
type = "Dead end" and | ||
result = count(CfgNode n | deadEnd(n) | n) | ||
or | ||
type = "Non-unique split kind" and | ||
result = count(CfgImpl::SplitImpl si | nonUniqueSplitKind(si, _) | si) | ||
or | ||
type = "Non-unique list order" and | ||
result = count(CfgImpl::SplitKind sk | nonUniqueListOrder(sk, _) | sk) | ||
or | ||
type = "Multiple toStrings" and | ||
result = count(CfgNode n | multipleToString(n, _) | n) | ||
or | ||
type = "CFG scope lacks initial AST node" and | ||
result = count(CfgScope s | scopeNoFirst(s) | s) | ||
or | ||
type = "Non-PostOrderTree Expr node" and | ||
result = count(Expr e | nonPostOrderExpr(e, _) | e) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/** | ||
* @name Control flow graph inconsistency counts | ||
* @description Counts the number of control flow graph inconsistencies of each type. This query is intended for internal use. | ||
* @kind diagnostic | ||
* @id rust/diagnostics/cfg-consistency-counts | ||
*/ | ||
|
||
import rust | ||
import codeql.rust.controlflow.internal.CfgConsistency as Consistency | ||
|
||
// see also `rust/diagnostics/cfg-consistency`, which lists the | ||
// individual inconsistency results. | ||
from string type, int num | ||
where num = Consistency::getCfgInconsistencyCounts(type) | ||
select type, num |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 13 additions & 0 deletions
13
rust/ql/test/query-tests/diagnostics/CfgConsistencyCounts.expected
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
| CFG scope lacks initial AST node | 0 | | ||
| Dead end | 0 | | ||
| Multiple successors of the same type | 0 | | ||
| Multiple toStrings | 0 | | ||
| Non-PostOrderTree Expr node | 0 | | ||
| Non-unique list order | 0 | | ||
| Non-unique set representation | 0 | | ||
| Non-unique split kind | 0 | | ||
| Simple and normal successors | 0 | | ||
| Splitting invariant 2 | 0 | | ||
| Splitting invariant 3 | 0 | | ||
| Splitting invariant 4 | 0 | | ||
| Splitting invariant 5 | 0 | |
1 change: 1 addition & 0 deletions
1
rust/ql/test/query-tests/diagnostics/CfgConsistencyCounts.qlref
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
queries/diagnostics/CfgConsistencyCounts.ql |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters