Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module;

private import semmle.code.Location
private import codeql.dataflow.DataFlow
private import semmle.code.java.Overlay

module Private {
import DataFlowPrivate
Expand All @@ -29,4 +30,6 @@ module JavaDataFlow implements InputSig<Location> {
predicate mayBenefitFromCallContext = Private::mayBenefitFromCallContext/1;

predicate viableImplInCallContext = Private::viableImplInCallContext/2;

predicate isEvaluatingInOverlay = isOverlay/0;
}
12 changes: 12 additions & 0 deletions shared/dataflow/codeql/dataflow/DataFlow.qll
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,18 @@ signature module InputSig<LocationSig Location> {

/** Holds if `fieldFlowBranchLimit` should be ignored for flow going into/out of `c`. */
default predicate ignoreFieldFlowBranchLimit(DataFlowCallable c) { none() }

/**
* Holds if the evaluator is currently evaluating with an overlay. The
* implementation of this predicate needs to be `overlay[local]`. For a
* language with no overlay support, `none()` is a valid implementation.
*
* When called from a local predicate, this predicate holds if we are in the
* overlay-only local evaluation. When called from a global predicate, this
* predicate holds if we are evaluating globally with overlay and base both
* visible.
*/
Copy link

Copilot AI Jun 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default isEvaluatingInOverlay predicate lacks the required overlay[local] annotation, so overlay-local evaluations won't see it. Add overlay[local] to its definition.

Suggested change
*/
*/
overlay[local]

Copilot uses AI. Check for mistakes.
default predicate isEvaluatingInOverlay() { none() }
}

module Configs<LocationSig Location, InputSig<Location> Lang> {
Expand Down
37 changes: 34 additions & 3 deletions shared/dataflow/codeql/dataflow/internal/DataFlowImplStage1.qll
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Provides an implementation of a fast initial pruning of global
* (interprocedural) data flow reachability (Stage 1).
*/
overlay[local?]
overlay[local?] // when this is removed, put `overlay[local?]` on `isOverlayNode`.
module;

private import codeql.util.Unit
Expand Down Expand Up @@ -129,14 +129,38 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {

private module AlertFiltering = AlertFilteringImpl<Location>;

/**
* Holds if the given node is visible in overlay-only local evaluation.
*
* This predicate needs to be `overlay[local?]`, either directly or
* through annotations from an outer scope. If `Node` is global for the
* language under analysis, then every node is considered an overlay
* node, which means there will effectively be no overlay-based
* filtering of sources and sinks.
*/
private predicate isOverlayNode(Node node) {
Comment on lines +135 to +141
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not give this predicate an explicit overlay annotation now?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The compiler gives a warning that it's redundant because the file module is also annotated overlay[local?].

isEvaluatingInOverlay() and
// Any local node is an overlay node if we are evaluating in overlay mode
node = node
Copy link

Copilot AI Jun 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The predicate isOverlayNode uses a tautology (node = node), so it doesn't actually distinguish overlay-visible nodes. Replace it with a predicate that checks the node's overlay locality (e.g., isLocalNode(node)).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The canonical way to write this is exists(node).

}

overlay[global]
pragma[nomagic]
private predicate isFilteredSource(Node source) {
Config::isSource(source, _) and
if Config::observeDiffInformedIncrementalMode()
then AlertFiltering::filterByLocation(Config::getASelectedSourceLocation(source))
else any()
else (
// If we are in base-only global evaluation, do not filter out any sources.
not isEvaluatingInOverlay()
or
// If we are in global evaluation with an overlay present, restrict
// sources to those visible in the overlay.
isOverlayNode(source)
)
}

overlay[global]
pragma[nomagic]
private predicate isFilteredSink(Node sink) {
(
Expand All @@ -145,7 +169,14 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
) and
if Config::observeDiffInformedIncrementalMode()
then AlertFiltering::filterByLocation(Config::getASelectedSinkLocation(sink))
else any()
else (
// If we are in base-only global evaluation, do not filter out any sinks.
not isEvaluatingInOverlay()
or
// If we are in global evaluation with an overlay present, restrict
// sinks to those visible in the overlay.
isOverlayNode(sink)
)
}

private predicate hasFilteredSource() { isFilteredSource(_) }
Expand Down
Loading