Merge pull request #20081 from d10c/d10c/diff-informed-phase-3-rust

Rust: Diff-informed queries: phase 3 (non-trivial locations)
This commit is contained in:
Nora Dimitrijević
2025-07-23 16:31:23 +02:00
committed by GitHub
8 changed files with 38 additions and 9 deletions

View File

@@ -34,6 +34,8 @@ module RegexInjectionConfig implements DataFlow::ConfigSig {
predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
any(AdditionalFlowStep s).step(nodeFrom, nodeTo)
}
predicate observeDiffInformedIncrementalMode() { any() }
}
/**

View File

@@ -79,6 +79,8 @@ module TaintedPathConfig implements DataFlow::StateConfigSig {
stateFrom instanceof NotNormalized and
stateTo instanceof NormalizedUnchecked
}
predicate observeDiffInformedIncrementalMode() { any() }
}
module TaintedPathFlow = TaintTracking::GlobalWithState<TaintedPathConfig>;

View File

@@ -26,6 +26,8 @@ module SqlInjectionConfig implements DataFlow::ConfigSig {
predicate isSink(DataFlow::Node node) { node instanceof Sink }
predicate isBarrier(DataFlow::Node barrier) { barrier instanceof Barrier }
predicate observeDiffInformedIncrementalMode() { any() }
}
module SqlInjectionFlow = TaintTracking::Global<SqlInjectionConfig>;

View File

@@ -37,6 +37,8 @@ module CleartextTransmissionConfig implements DataFlow::ConfigSig {
// make sources barriers so that we only report the closest instance
isSource(node)
}
predicate observeDiffInformedIncrementalMode() { any() }
}
module CleartextTransmissionFlow = TaintTracking::Global<CleartextTransmissionConfig>;

View File

@@ -45,6 +45,8 @@ module CleartextLoggingConfig implements DataFlow::ConfigSig {
isSink(node) and
c.getAReadContent() instanceof DataFlow::TuplePositionContent
}
predicate observeDiffInformedIncrementalMode() { any() }
}
module CleartextLoggingFlow = TaintTracking::Global<CleartextLoggingConfig>;

View File

@@ -32,6 +32,8 @@ module UncontrolledAllocationConfig implements DataFlow::ConfigSig {
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node barrier) { barrier instanceof Barrier }
predicate observeDiffInformedIncrementalMode() { any() }
}
module UncontrolledAllocationFlow = TaintTracking::Global<UncontrolledAllocationConfig>;

View File

@@ -28,10 +28,33 @@ module AccessAfterLifetimeConfig implements DataFlow::ConfigSig {
predicate isSink(DataFlow::Node node) { node instanceof AccessAfterLifetime::Sink }
predicate isBarrier(DataFlow::Node barrier) { barrier instanceof AccessAfterLifetime::Barrier }
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSourceLocation(DataFlow::Node source) {
exists(Variable target, DataFlow::Node sink | result = target.getLocation() |
isSink(sink) and
narrowDereferenceAfterLifetime(source, sink, target)
)
}
}
module AccessAfterLifetimeFlow = TaintTracking::Global<AccessAfterLifetimeConfig>;
pragma[inline]
predicate narrowDereferenceAfterLifetime(DataFlow::Node source, DataFlow::Node sink, Variable target) {
// check that the dereference is outside the lifetime of the target
AccessAfterLifetime::dereferenceAfterLifetime(source, sink, target) and
// include only results inside `unsafe` blocks, as other results tend to be false positives
(
sink.asExpr().getExpr().getEnclosingBlock*().isUnsafe() or
sink.asExpr().getExpr().getEnclosingCallable().(Function).isUnsafe()
) and
// exclude cases with sources / sinks in macros, since these results are difficult to interpret
not source.asExpr().getExpr().isFromMacroExpansion() and
not sink.asExpr().getExpr().isFromMacroExpansion()
}
from
AccessAfterLifetimeFlow::PathNode sourceNode, AccessAfterLifetimeFlow::PathNode sinkNode,
Variable target
@@ -39,14 +62,6 @@ 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) and
// include only results inside `unsafe` blocks, as other results tend to be false positives
(
sinkNode.getNode().asExpr().getExpr().getEnclosingBlock*().isUnsafe() or
sinkNode.getNode().asExpr().getExpr().getEnclosingCallable().(Function).isUnsafe()
) and
// exclude cases with sources / sinks in macros, since these results are difficult to interpret
not sourceNode.getNode().asExpr().getExpr().isFromMacroExpansion() and
not sinkNode.getNode().asExpr().getExpr().isFromMacroExpansion()
narrowDereferenceAfterLifetime(sourceNode.getNode(), sinkNode.getNode(), target)
select sinkNode.getNode(), sourceNode, sinkNode,
"Access of a pointer to $@ after its lifetime has ended.", target, target.toString()

View File

@@ -32,6 +32,8 @@ module AccessInvalidPointerConfig implements DataFlow::ConfigSig {
// make sinks barriers so that we only report the closest instance
isSink(node)
}
predicate observeDiffInformedIncrementalMode() { any() }
}
module AccessInvalidPointerFlow = TaintTracking::Global<AccessInvalidPointerConfig>;