mirror of
https://github.com/github/codeql.git
synced 2026-04-22 23:35:14 +02:00
Merge pull request #17763 from geoffw0/cfgcount3
Rust: Count number of CFG inconsistencies
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
15
rust/ql/src/queries/diagnostics/CfgConsistencyCounts.ql
Normal file
15
rust/ql/src/queries/diagnostics/CfgConsistencyCounts.ql
Normal file
@@ -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
|
||||
@@ -3,9 +3,23 @@
|
||||
*/
|
||||
|
||||
import rust
|
||||
private import codeql.rust.controlflow.internal.CfgConsistency as CfgConsistency
|
||||
|
||||
/**
|
||||
* Gets a count of the total number of lines of code in the database.
|
||||
*/
|
||||
int getLinesOfCode() { result = sum(File f | | f.getNumberOfLinesOfCode()) }
|
||||
|
||||
/**
|
||||
* Gets a count of the total number of lines of code from the source code directory in the database.
|
||||
*/
|
||||
int getLinesOfUserCode() {
|
||||
result = sum(File f | exists(f.getRelativePath()) | f.getNumberOfLinesOfCode())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a count of the total number of control flow graph inconsistencies in the database.
|
||||
*/
|
||||
int getTotalCfgInconsistencies() {
|
||||
result = sum(string type | | CfgConsistency::getCfgInconsistencyCounts(type))
|
||||
}
|
||||
|
||||
@@ -33,4 +33,6 @@ where
|
||||
key = "Lines of code extracted" and value = getLinesOfCode().toString()
|
||||
or
|
||||
key = "Lines of user code extracted" and value = getLinesOfUserCode().toString()
|
||||
or
|
||||
key = "Inconsistencies - CFG" and value = getTotalCfgInconsistencies().toString()
|
||||
select key, value
|
||||
|
||||
@@ -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 |
|
||||
@@ -0,0 +1 @@
|
||||
queries/diagnostics/CfgConsistencyCounts.ql
|
||||
@@ -5,5 +5,6 @@
|
||||
| Files extracted - total | 7 |
|
||||
| Files extracted - with errors | 2 |
|
||||
| Files extracted - without errors | 5 |
|
||||
| Inconsistencies - CFG | 0 |
|
||||
| Lines of code extracted | 59 |
|
||||
| Lines of user code extracted | 59 |
|
||||
|
||||
Reference in New Issue
Block a user