Data flow: Add hook for preventing lambda dispatch in source call contexts#21592
Data flow: Add hook for preventing lambda dispatch in source call contexts#21592hvitved wants to merge 2 commits intogithub:mainfrom
Conversation
292fb0a to
1efb323
Compare
1efb323 to
aa52b10
Compare
There was a problem hiding this comment.
Pull request overview
Adds a configurable hook in the shared dataflow library to prevent resolving lambda dispatch when using source call-context flow features (implemented for C# via a special “source context parameter” type), so call-context–sensitive analyses can reject spurious edges.
Changes:
- Extend shared dataflow
InputSig/TypeFlow plumbing with a hook for assigning a special parameter-node type in source call-context scenarios. - Implement the hook for C# by introducing a dedicated
DataFlowTypevariant and compatibility behavior. - Add a C# model-generator regression test snippet to ensure the added call-site pattern doesn’t affect summary generation.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll | Threads a new TypeFlowInput predicate and applies a special type for parameters in source call-context. |
| shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll | Implements the new TypeFlowInput hook for forward analysis; defaults it to none() for reverse. |
| shared/dataflow/codeql/dataflow/DataFlow.qll | Adds a new InputSig extension point with detailed documentation/example. |
| csharp/ql/test/utils/modelgenerator/dataflow/Summaries.cs | Adds a small call-site intended to guard summary generation behavior. |
| csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll | Introduces a C#-specific “source context parameter” dataflow type and compatibility handling. |
| csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplSpecific.qll | Wires the new InputSig hook to return the C# special type. |
Comments suppressed due to low confidence (1)
shared/dataflow/codeql/dataflow/DataFlow.qll:91
- The example explanation is a little confusing because it refers to a “call edge from (3) to (2)”, but (2) is the assignment statement (not the lambda itself). Consider clarifying that (3) can still dispatch to the lambda assigned at (2), to avoid readers misinterpreting which edge is meant.
* If a source call context flow feature is used, `a` can be assigned a special
* type that is incompatible with the type of _any_ lambda expression, which will
* prevent the call edge from (1) to (4). Note that the call edge from (3) to (2)
* will still be valid.
| } | ||
|
|
||
| pragma[nomagic] | ||
| predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { |
There was a problem hiding this comment.
This predicate should also have added the compatibleTypesSourceContextParameterTypeLeft(t1, t2) case, I think.
| * prevent the call edge from (1) to (4). Note that the call edge from (3) to (2) | ||
| * will still be valid. | ||
| */ | ||
| default DataFlowType getSourceContextParameterNodeType() { none() } |
There was a problem hiding this comment.
I wonder whether this type ought to be parameterised on the parameter. Conceptually it's a subtype of whatever callback type the parameter has and there could be multiple mutually disjoint callback types. And if this type is introduced as a singleton then it could conceptually ruin that disjointness.
Consider the following example:
Because of the call at (4), both (1) and (3) are calls that can reach a sink.
However, when we use the flow feature
FeatureHasSourceCallContext(orFeatureEqualSourceSinkCallContext), we want to reject the call edge from (1) to (4).We achieve this using the
TypeFlowmodule, by assigning the parameteraa special type that is incompatible with all lambda types. This is currently only implemented for C#, so all other languages should be unaffected by this change.Thanks to @aschackmull for pointing me in the right direction.