Skip to content

Commit 3a1b618

Browse files
committed
Cpp: Replace sink inlining with a forward scan from source.
1 parent 590e93d commit 3a1b618

File tree

2 files changed

+42
-6
lines changed

2 files changed

+42
-6
lines changed

cpp/ql/lib/semmle/code/cpp/security/InvalidPointerDereference/InvalidPointerToDereference.qll

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,26 @@ private module InvalidPointerToDerefBarrier {
160160
}
161161
}
162162

163+
/**
164+
* BEWARE: This configuration uses an unrestricted sink, so accessing its full
165+
* flow computation or any stages beyond the first 2 will likely diverge.
166+
* Stage 1 will still be fast and we use it to restrict the subsequent sink
167+
* computation.
168+
*/
169+
private module InvalidPointerReachesConfig implements DataFlow::ConfigSig {
170+
predicate isSource(DataFlow::Node source) { invalidPointerToDerefSource(_, _, source) }
171+
172+
predicate isSink(DataFlow::Node sink) { any() }
173+
174+
predicate isBarrier(DataFlow::Node node) { InvalidPointerToDerefConfig::isBarrier(node) }
175+
176+
int fieldFlowBranchLimit() { result = invalidPointerToDereferenceFieldFlowBranchLimit() }
177+
}
178+
179+
private module InvalidPointerReachesFlow = DataFlow::Global<InvalidPointerReachesConfig>;
180+
181+
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon
182+
163183
/**
164184
* A configuration to track flow from a pointer-arithmetic operation found
165185
* by `AllocToInvalidPointerConfig` to a dereference of the pointer.
@@ -173,8 +193,13 @@ private module InvalidPointerToDerefConfig implements DataFlow::StateConfigSig {
173193
invalidPointerToDerefSource(_, pai, source)
174194
}
175195

176-
pragma[inline]
177-
predicate isSink(DataFlow::Node sink) { isInvalidPointerDerefSink(sink, _, _, _, _) }
196+
predicate isSink(DataFlow::Node sink) {
197+
exists(DataFlowImplCommon::NodeEx n |
198+
InvalidPointerReachesFlow::Stages::Stage1::sinkNode(n, _) and
199+
n.asNode() = sink and
200+
isInvalidPointerDerefSink(sink, _, _, _, _)
201+
)
202+
}
178203

179204
predicate isSink(DataFlow::Node sink, FlowState pai) { none() }
180205

shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2773,8 +2773,6 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
27732773
}
27742774

27752775
/**
2776-
* INTERNAL: Only for debugging.
2777-
*
27782776
* Provides a graph representation of the data flow in this stage suitable for use in a `path-problem` query.
27792777
*/
27802778
additional module Graph {
@@ -4634,6 +4632,8 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
46344632
*/
46354633
predicate stageStats = Debug::stageStats/10;
46364634

4635+
private module Stage1alias = Stage1;
4636+
46374637
private module Stage2alias = Stage2;
46384638

46394639
private module Stage3alias = Stage3;
@@ -4643,18 +4643,29 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
46434643
private module Stage5alias = Stage5;
46444644

46454645
/**
4646-
* INTERNAL: Only for debugging.
4646+
* INTERNAL: Subject to change without notice.
46474647
*
46484648
* Contains references to individual pruning stages.
46494649
*/
4650-
module Debug {
4650+
module Stages {
4651+
module Stage1 = Stage1alias;
4652+
46514653
module Stage2 = Stage2alias;
46524654

46534655
module Stage3 = Stage3alias;
46544656

46554657
module Stage4 = Stage4alias;
46564658

46574659
module Stage5 = Stage5alias;
4660+
}
4661+
4662+
/**
4663+
* INTERNAL: Only for debugging.
4664+
*
4665+
* Contains references to individual pruning stages and stage statistics.
4666+
*/
4667+
module Debug {
4668+
import Stages
46584669

46594670
predicate stageStats1(
46604671
int n, string stage, int nodes, int fields, int conscand, int states, int tuples,

0 commit comments

Comments
 (0)