-
Notifications
You must be signed in to change notification settings - Fork 1.9k
C++: Modernize MustFlow and fix allowInterproceduralFlow in the case of direct recursion
#21331
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
26a1f48
73194a5
366ebca
4efbc6e
e299ccc
31895c0
3aa2124
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| --- | ||
| category: fix | ||
| --- | ||
| * The `allowInterproceduralFlow` predicate of must-flow data flow configurations now correctly handles direct recursion. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| --- | ||
| category: breaking | ||
| --- | ||
| * `MustFlow`, the inter-procedural must-flow data flow analysis library, has been re-worked to use parameterized modules. Like in the case of data flow and taint tracking, instead of extending the `MustFlowConfiguration` class, the user should now implement a module with the `MustFlow::ConfigSig` signature, and instantiate the `MustFlow::Global` parameterized module with the implemented module. |
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -8,83 +8,145 @@ private import cpp | |||||||
| private import semmle.code.cpp.ir.IR | ||||||||
|
|
||||||||
| /** | ||||||||
| * A configuration of a data flow analysis that performs must-flow analysis. This is different | ||||||||
| * from `DataFlow.qll` which performs may-flow analysis (i.e., it finds paths where the source _may_ | ||||||||
| * flow to the sink). | ||||||||
| * | ||||||||
| * Like in `DataFlow.qll`, each use of the `MustFlow.qll` library must define its own unique extension | ||||||||
| * of this abstract class. To create a configuration, extend this class with a subclass whose | ||||||||
| * characteristic predicate is a unique singleton string and override `isSource`, `isSink` (and | ||||||||
| * `isAdditionalFlowStep` if additional steps are required). | ||||||||
| * Provides an inter-procedural must-flow data flow analysis. | ||||||||
| */ | ||||||||
| abstract class MustFlowConfiguration extends string { | ||||||||
| bindingset[this] | ||||||||
| MustFlowConfiguration() { any() } | ||||||||
|
|
||||||||
| /** | ||||||||
| * Holds if `source` is a relevant data flow source. | ||||||||
| */ | ||||||||
| abstract predicate isSource(Instruction source); | ||||||||
|
|
||||||||
| module MustFlow { | ||||||||
jketema marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
| /** | ||||||||
| * Holds if `sink` is a relevant data flow sink. | ||||||||
| * An input configuration of a data flow analysis that performs must-flow analysis. This is different | ||||||||
| * from `DataFlow.qll` which performs may-flow analysis (i.e., it finds paths where the source _may_ | ||||||||
| * flow to the sink). | ||||||||
| */ | ||||||||
| abstract predicate isSink(Operand sink); | ||||||||
|
|
||||||||
| /** | ||||||||
| * Holds if data flow through `instr` is prohibited. | ||||||||
| */ | ||||||||
| predicate isBarrier(Instruction instr) { none() } | ||||||||
| signature module ConfigSig { | ||||||||
| /** | ||||||||
| * Holds if `source` is a relevant data flow source. | ||||||||
| */ | ||||||||
| predicate isSource(Instruction source); | ||||||||
|
|
||||||||
| /** | ||||||||
| * Holds if `sink` is a relevant data flow sink. | ||||||||
| */ | ||||||||
| predicate isSink(Operand sink); | ||||||||
|
|
||||||||
| /** | ||||||||
| * Holds if data flow through `instr` is prohibited. | ||||||||
| */ | ||||||||
| default predicate isBarrier(Instruction instr) { none() } | ||||||||
|
|
||||||||
| /** | ||||||||
| * Holds if the additional flow step from `node1` to `node2` must be taken | ||||||||
| * into account in the analysis. | ||||||||
| */ | ||||||||
| default predicate isAdditionalFlowStep(Operand node1, Instruction node2) { none() } | ||||||||
|
|
||||||||
| /** Holds if this configuration allows flow from arguments to parameters. */ | ||||||||
| default predicate allowInterproceduralFlow() { any() } | ||||||||
| } | ||||||||
|
|
||||||||
| /** | ||||||||
| * Holds if the additional flow step from `node1` to `node2` must be taken | ||||||||
| * into account in the analysis. | ||||||||
| * Constructs a global must-flow computation. | ||||||||
| */ | ||||||||
| predicate isAdditionalFlowStep(Operand node1, Instruction node2) { none() } | ||||||||
|
|
||||||||
| /** Holds if this configuration allows flow from arguments to parameters. */ | ||||||||
| predicate allowInterproceduralFlow() { any() } | ||||||||
| module Global<ConfigSig Config> { | ||||||||
| import Config | ||||||||
|
|
||||||||
| /** | ||||||||
| * Holds if data must flow from `source` to `sink`. | ||||||||
| * | ||||||||
| * The corresponding paths are generated from the end-points and the graph | ||||||||
| * included in the module `PathGraph`. | ||||||||
| */ | ||||||||
| predicate flowPath(PathNode source, PathSink sink) { | ||||||||
|
||||||||
| predicate flowPath(PathNode source, PathSink sink) { | |
| predicate flowPath(PathNode source, PathNode sink) { | |
| sink instanceof PathSink and |
Copilot
AI
Feb 17, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
flowPath is exported but its signature exposes PathSink, which is a private class. This makes the public API awkward for consumers (they can’t name PathSink in their own type declarations). Consider changing flowPath to accept PathNode for the sink parameter and enforce sink instanceof PathSink in the body, or make PathSink non-private (and document it as part of the API).
Uh oh!
There was an error while loading. Please reload this page.