Files
codeql/rust/ql/src/queries/security/CWE-825/AccessAfterLifetime.ql

67 lines
2.5 KiB
Plaintext

/**
* @name Access of a pointer after its lifetime has ended
* @description Dereferencing a pointer after the lifetime of its target has ended
* causes undefined behavior and may result in memory corruption.
* @kind path-problem
* @problem.severity error
* @security-severity 9.8
* @precision medium
* @id rust/access-after-lifetime-ended
* @tags reliability
* security
* external/cwe/cwe-825
*/
import rust
import codeql.rust.dataflow.DataFlow
import codeql.rust.dataflow.TaintTracking
import codeql.rust.security.AccessAfterLifetimeExtensions
import AccessAfterLifetimeFlow::PathGraph
/**
* A data flow configuration for detecting accesses to a pointer after its
* lifetime has ended.
*/
module AccessAfterLifetimeConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) {
node instanceof AccessAfterLifetime::Source and
// exclude cases with sources in macros, since these results are difficult to interpret
not node.asExpr().isFromMacroExpansion() and
AccessAfterLifetime::sourceValueScope(node, _, _)
}
predicate isSink(DataFlow::Node node) {
node instanceof AccessAfterLifetime::Sink and
// Exclude cases with sinks in macros, since these results are difficult to interpret
not node.asExpr().isFromMacroExpansion() and
// TODO: Remove this condition if it can be done without negatively
// impacting performance. This condition only include nodes with
// corresponding to an expression. This excludes sinks from models-as-data.
exists(node.asExpr())
}
predicate isBarrier(DataFlow::Node barrier) { barrier instanceof AccessAfterLifetime::Barrier }
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSourceLocation(DataFlow::Node source) {
exists(Variable target |
AccessAfterLifetime::sourceValueScope(source, target, _) and
result = [target.getLocation(), source.getLocation()]
)
}
}
module AccessAfterLifetimeFlow = TaintTracking::Global<AccessAfterLifetimeConfig>;
from
AccessAfterLifetimeFlow::PathNode sourceNode, AccessAfterLifetimeFlow::PathNode sinkNode,
Variable target
where
// flow from a pointer or reference to the dereference
AccessAfterLifetimeFlow::flowPath(sourceNode, sinkNode) and
// check that the dereference is outside the lifetime of the target
AccessAfterLifetime::dereferenceAfterLifetime(sourceNode.getNode(), sinkNode.getNode(), target)
select sinkNode.getNode(), sourceNode, sinkNode,
"Access of a pointer to $@ after its lifetime has ended.", target, target.toString()