From a645a9e8295e574504f712300c96f0e99ac89b7d Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 4 Nov 2024 18:50:45 +0000 Subject: [PATCH 1/4] Rust: Add getInconsistencyCounts predicate to the shared DataFlowImplConsistency.qll, so it's possibly to access inconsistency data as a whole. --- .../internal/DataFlowImplConsistency.qll | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImplConsistency.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImplConsistency.qll index ca523e179c4..f46b62f51e2 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImplConsistency.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImplConsistency.qll @@ -337,4 +337,107 @@ module MakeConsistency< ) ) } + + /** + * Gets counts of inconsistencies of each type. + */ + int getInconsistencyCounts(string type) { + // total results from all the AST consistency query predicates. + type = "Node should have one enclosing callable" and + result = count(Node n | uniqueEnclosingCallable(n, _)) + or + type = "Call should have one enclosing callable" and + result = count(DataFlowCall c | uniqueCallEnclosingCallable(c, _)) + or + type = "Node should have one type" and + result = count(Node n | uniqueType(n, _)) + or + type = "Node should have one location" and + result = count(Node n | uniqueNodeLocation(n, _)) + or + type = "Nodes without location" and + result = count( | missingLocation(_) | 1) + or + type = "Node should have one toString" and + result = count(Node n | uniqueNodeToString(n, _)) + or + type = "Callable mismatch for parameter" and + result = count(ParameterNode p | parameterCallable(p, _)) + or + type = "Local flow step does not preserve enclosing callable" and + result = count(Node n1, Node n2 | localFlowIsLocal(n1, n2, _)) + or + type = "Read step does not preserve enclosing callable" and + result = count(Node n1, Node n2 | readStepIsLocal(n1, n2, _)) + or + type = "Store step does not preserve enclosing callable" and + result = count(Node n1, Node n2 | storeStepIsLocal(n1, n2, _)) + or + type = "Type compatibility predicate is not reflexive" and + result = count(DataFlowType t | compatibleTypesReflexive(t, _)) + or + type = "Call context for isUnreachableInCall is inconsistent with call graph" and + result = count(Node n, DataFlowCall call | unreachableNodeCCtx(n, call, _)) + or + type = "Node and call does not share enclosing callable" and + result = count(DataFlowCall call, Node n | localCallNodes(call, n, _)) + or + type = "PostUpdateNode should not equal its pre-update node" and + result = count(PostUpdateNode n | postIsNotPre(n, _)) + or + type = "PostUpdateNode should have one pre-update node" and + result = count(PostUpdateNode n | postHasUniquePre(n, _)) + or + type = "Node has multiple PostUpdateNodes" and + result = count(Node n | uniquePostUpdate(n, _)) + or + type = "PostUpdateNode does not share callable with its pre-update node" and + result = count(PostUpdateNode n | postIsInSameCallable(n, _)) + or + type = "Origin of readStep is missing a PostUpdateNode" and + result = count(Node n | reverseRead(n, _)) + or + type = "ArgumentNode is missing PostUpdateNode" and + result = count(ArgumentNode n | argHasPostUpdate(n, _)) + or + type = "PostUpdateNode should not be the target of local flow" and + result = count(PostUpdateNode n | postWithInFlow(n, _)) + or + type = "Call context too large" and + result = + count(DataFlowCall call, DataFlowCall ctx, DataFlowCallable callable | + viableImplInCallContextTooLarge(call, ctx, callable) + ) + or + type = "Parameters with overlapping positions" and + result = + count(DataFlowCallable c, ParameterPosition pos, Node p | + uniqueParameterNodeAtPosition(c, pos, p, _) + ) + or + type = "Parameter node with multiple positions" and + result = + count(DataFlowCallable c, ParameterPosition pos, Node p | + uniqueParameterNodePosition(c, pos, p, _) + ) + or + type = "Non-unique content approximation" and + result = count(Content c | uniqueContentApprox(c, _)) + or + type = "Node steps to itself" and + result = count(Node n | identityLocalStep(n, _)) + or + type = "Missing call for argument node" and + result = count(ArgumentNode n | missingArgumentCall(n, _)) + or + type = "Multiple calls for argument node" and + result = count(ArgumentNode arg, DataFlowCall call | multipleArgumentCall(arg, call, _)) + or + type = "Lambda call enclosing callable mismatch" and + result = + count(DataFlowCall call, Node receiver | lambdaCallEnclosingCallableMismatch(call, receiver)) + or + type = "Speculative step already hasM Model" and + result = count(Node n1, Node n2 | speculativeStepAlreadyHasModel(n1, n2, _)) + } } From 91ebc0eb45d25dcaf8eab37b6ec17deb67d43525 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 4 Nov 2024 18:49:37 +0000 Subject: [PATCH 2/4] Rust: Add metadata to the DataFlowConsistency.ql query. --- rust/ql/consistency-queries/DataFlowConsistency.ql | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/rust/ql/consistency-queries/DataFlowConsistency.ql b/rust/ql/consistency-queries/DataFlowConsistency.ql index 7d63aa7d68a..3513121f260 100644 --- a/rust/ql/consistency-queries/DataFlowConsistency.ql +++ b/rust/ql/consistency-queries/DataFlowConsistency.ql @@ -1,3 +1,10 @@ +/** + * @name Data flow inconsistencies + * @description Lists the data flow inconsistencies in the database. This query is intended for internal use. + * @kind table + * @id rust/diagnostics/data-flow-consistency + */ + import codeql.rust.dataflow.DataFlow::DataFlow as DataFlow private import rust private import codeql.rust.dataflow.internal.DataFlowImpl From 30cc55005dd0bf746bdcf5aee7830a83ff8621ae Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 4 Nov 2024 18:48:31 +0000 Subject: [PATCH 3/4] Rust: Add rust/diagnostics/data-flow-consistency-counts query for data flow inconsistency counts. --- .../diagnostics/DataFlowConsistencyCounts.ql | 21 ++++++++++++++ .../DataFlowConsistencyCounts.expected | 29 +++++++++++++++++++ .../DataFlowConsistencyCounts.qlref | 1 + 3 files changed, 51 insertions(+) create mode 100644 rust/ql/src/queries/diagnostics/DataFlowConsistencyCounts.ql create mode 100644 rust/ql/test/query-tests/diagnostics/DataFlowConsistencyCounts.expected create mode 100644 rust/ql/test/query-tests/diagnostics/DataFlowConsistencyCounts.qlref diff --git a/rust/ql/src/queries/diagnostics/DataFlowConsistencyCounts.ql b/rust/ql/src/queries/diagnostics/DataFlowConsistencyCounts.ql new file mode 100644 index 00000000000..79c582adb08 --- /dev/null +++ b/rust/ql/src/queries/diagnostics/DataFlowConsistencyCounts.ql @@ -0,0 +1,21 @@ +/** + * @name Data flow inconsistency counts + * @description Counts the number of data flow inconsistencies of each type. This query is intended for internal use. + * @kind diagnostic + * @id rust/diagnostics/data-flow-consistency-counts + */ + +private import rust +private import codeql.rust.dataflow.internal.DataFlowImpl +private import codeql.rust.dataflow.internal.TaintTrackingImpl +private import codeql.dataflow.internal.DataFlowImplConsistency + +private module Input implements InputSig { } + +// see also `rust/diagnostics/data-flow-consistency`, which lists the +// individual inconsistency results. +from string type, int num +where + num = + MakeConsistency::getInconsistencyCounts(type) +select type, num diff --git a/rust/ql/test/query-tests/diagnostics/DataFlowConsistencyCounts.expected b/rust/ql/test/query-tests/diagnostics/DataFlowConsistencyCounts.expected new file mode 100644 index 00000000000..abc5a99fbd1 --- /dev/null +++ b/rust/ql/test/query-tests/diagnostics/DataFlowConsistencyCounts.expected @@ -0,0 +1,29 @@ +| ArgumentNode is missing PostUpdateNode | 0 | +| Call context for isUnreachableInCall is inconsistent with call graph | 0 | +| Call context too large | 0 | +| Call should have one enclosing callable | 7 | +| Callable mismatch for parameter | 0 | +| Lambda call enclosing callable mismatch | 0 | +| Local flow step does not preserve enclosing callable | 0 | +| Missing call for argument node | 0 | +| Multiple calls for argument node | 0 | +| Node and call does not share enclosing callable | 0 | +| Node has multiple PostUpdateNodes | 0 | +| Node should have one enclosing callable | 0 | +| Node should have one location | 0 | +| Node should have one toString | 0 | +| Node should have one type | 0 | +| Node steps to itself | 0 | +| Nodes without location | 0 | +| Non-unique content approximation | 0 | +| Origin of readStep is missing a PostUpdateNode | 0 | +| Parameter node with multiple positions | 0 | +| Parameters with overlapping positions | 0 | +| PostUpdateNode does not share callable with its pre-update node | 0 | +| PostUpdateNode should have one pre-update node | 0 | +| PostUpdateNode should not be the target of local flow | 0 | +| PostUpdateNode should not equal its pre-update node | 0 | +| Read step does not preserve enclosing callable | 0 | +| Speculative step already hasM Model | 0 | +| Store step does not preserve enclosing callable | 0 | +| Type compatibility predicate is not reflexive | 0 | diff --git a/rust/ql/test/query-tests/diagnostics/DataFlowConsistencyCounts.qlref b/rust/ql/test/query-tests/diagnostics/DataFlowConsistencyCounts.qlref new file mode 100644 index 00000000000..128d80b2291 --- /dev/null +++ b/rust/ql/test/query-tests/diagnostics/DataFlowConsistencyCounts.qlref @@ -0,0 +1 @@ +queries/diagnostics/DataFlowConsistencyCounts.ql From c8c747a11022432d5507982b8f2bf45091566ec8 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 4 Nov 2024 18:58:09 +0000 Subject: [PATCH 4/4] Rust: Add total data flow inconsistencies to rust/summary/summary-statistics. --- rust/ql/src/queries/summary/Stats.qll | 18 +++++++++++++++++- rust/ql/src/queries/summary/SummaryStats.ql | 2 ++ .../diagnostics/SummaryStats.expected | 1 + 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/rust/ql/src/queries/summary/Stats.qll b/rust/ql/src/queries/summary/Stats.qll index 69453f68fff..aec671098eb 100644 --- a/rust/ql/src/queries/summary/Stats.qll +++ b/rust/ql/src/queries/summary/Stats.qll @@ -3,8 +3,11 @@ */ import rust -import codeql.rust.AstConsistency as AstConsistency +private import codeql.rust.dataflow.internal.DataFlowImpl +private import codeql.rust.dataflow.internal.TaintTrackingImpl +private import codeql.rust.AstConsistency as AstConsistency private import codeql.rust.controlflow.internal.CfgConsistency as CfgConsistency +private import codeql.dataflow.internal.DataFlowImplConsistency as DataFlowImplConsistency /** * Gets a count of the total number of lines of code in the database. @@ -31,3 +34,16 @@ int getTotalAstInconsistencies() { int getTotalCfgInconsistencies() { result = sum(string type | | CfgConsistency::getCfgInconsistencyCounts(type)) } + +private module Input implements DataFlowImplConsistency::InputSig { } + +/** + * Gets a count of the total number of data flow inconsistencies in the database. + */ +int getTotalDataFlowInconsistencies() { + result = + sum(string type | + | + DataFlowImplConsistency::MakeConsistency::getInconsistencyCounts(type) + ) +} diff --git a/rust/ql/src/queries/summary/SummaryStats.ql b/rust/ql/src/queries/summary/SummaryStats.ql index d16e229b4dd..3f24eb50d19 100644 --- a/rust/ql/src/queries/summary/SummaryStats.ql +++ b/rust/ql/src/queries/summary/SummaryStats.ql @@ -35,4 +35,6 @@ where key = "Inconsistencies - AST" and value = getTotalAstInconsistencies() or key = "Inconsistencies - CFG" and value = getTotalCfgInconsistencies() + or + key = "Inconsistencies - data flow" and value = getTotalDataFlowInconsistencies() select key, value diff --git a/rust/ql/test/query-tests/diagnostics/SummaryStats.expected b/rust/ql/test/query-tests/diagnostics/SummaryStats.expected index 56fda0b4f8e..37ec4eb1425 100644 --- a/rust/ql/test/query-tests/diagnostics/SummaryStats.expected +++ b/rust/ql/test/query-tests/diagnostics/SummaryStats.expected @@ -7,5 +7,6 @@ | Files extracted - without errors | 5 | | Inconsistencies - AST | 0 | | Inconsistencies - CFG | 0 | +| Inconsistencies - data flow | 7 | | Lines of code extracted | 59 | | Lines of user code extracted | 59 |