/** * @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; 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()