Skip to content

Java: Use the shared BasicBlocks library. #19505

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

Merged
merged 7 commits into from
May 21, 2025

Conversation

aschackmull
Copy link
Contributor

What the title says. Also, since BasicBlock is now no longer cast-compatible with ControlFlowNode there's no reason to use all the bb-prefixed names, so I've deprecated those and switched to the defaults provided by the shared library.

@Copilot Copilot AI review requested due to automatic review settings May 16, 2025 12:28
@aschackmull aschackmull requested review from a team as code owners May 16, 2025 12:28
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Migration to the shared BasicBlock library and deprecation of legacy bb* methods and predicates, updating call sites to use the new BasicBlock API.

  • Replaced legacy dominance and successor/predecessor methods (bbDominates, getABBSuccessor, etc.) with the shared-library methods (dominates, getASuccessor, etc.).
  • Updated imports, removed unused Dominance imports, and augmented qlpack.yml to depend on codeql/controlflow.
  • Introduced SuccessorType definitions, updated BasicBlocks.qll to use the shared BasicBlock implementation, and added change notes.

Reviewed Changes

Copilot reviewed 39 out of 39 changed files in this pull request and generated no comments.

Show a summary per file
File Description
java/ql/lib/semmle/code/java/security/PathSanitizer.qll Swapped bbDominates for dominates.
java/ql/lib/semmle/code/java/security/AndroidWebViewCertificateValidationQuery.qll Swapped bbPostDominates for postDominates.
java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionSpecific.qll Updated idOf to use getFirstNode().getAstNode().
java/ql/lib/semmle/code/java/dataflow/internal/SsaImpl.qll Removed Dom import; switched to immediatelyDominates and getASuccessor.
java/ql/lib/semmle/code/java/dataflow/internal/DataFlowUtil.qll Replaced getABBSuccessor calls with getASuccessor.
java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll Swapped bbIDominates and getABBSuccessor for shared APIs.
java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll Removed Dom import; switched to shared dominator/successor APIs.
java/ql/lib/semmle/code/java/dataflow/TypeFlow.qll Replaced getABBPredecessor and bbDominates with new methods.
java/ql/lib/semmle/code/java/dataflow/RangeAnalysis.qll Updated idOf and successor calls to use getFirstNode/getASuccessor.
java/ql/lib/semmle/code/java/dataflow/Nullness.qll Replaced all getABBSuccessor/getAST* with new basic-block methods.
java/ql/lib/semmle/code/java/controlflow/internal/GuardsLogic.qll Updated dominance checks to use dominates and new successor logic.
java/ql/lib/semmle/code/java/controlflow/UnreachableBlocks.qll Replaced predecessor and dominance calls with shared methods.
java/ql/lib/semmle/code/java/controlflow/SuccessorType.qll Added new SuccessorType hierarchy.
java/ql/lib/semmle/code/java/controlflow/Paths.qll Swapped legacy bb* calls for shared successor/dominance methods.
java/ql/lib/semmle/code/java/controlflow/Guards.qll Updated getTestSuccessor, dominance checks to new form.
java/ql/lib/semmle/code/java/controlflow/Dominance.qll Deprecated old predicates, forwarding to new methods.
java/ql/lib/semmle/code/java/controlflow/BasicBlocks.qll Imported and extended shared BasicBlock implementation.
java/ql/lib/qlpack.yml Added codeql/controlflow dependency.
java/ql/lib/change-notes/2025-05-16-shared-basicblocks.md Documented deprecation and migration to shared BasicBlock.
cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticCFG.qll Renamed bbDominates to dominates.
Comments suppressed due to low confidence (3)

java/ql/lib/semmle/code/java/controlflow/BasicBlocks.qll:6

  • [nitpick] The Dominance import is now redundant since the shared BasicBlock API provides dominance predicates; consider removing this import to clean up unused dependencies.
import Dominance

java/ql/lib/semmle/code/java/controlflow/SuccessorType.qll:1

  • The new SuccessorType hierarchy introduced here doesn’t appear to have dedicated tests; consider adding unit tests to cover NormalSuccessor, ConditionalSuccessor, and ExceptionSuccessor handling.
import java

java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll:86

  • The BasicBlock type isn’t aliased in this module; you should add private import java as J and class BasicBlock = J::BasicBlock; at the top to ensure the correct type is used.
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) {

}

/** Exit points for basic-block control-flow. */
private predicate bbSink(BasicBlock exit) { exit.getLastNode() instanceof ControlFlow::ExitNode }

/** Reversed `bbSucc`. */
private predicate bbPred(BasicBlock post, BasicBlock pre) { post = pre.getABBSuccessor() }
private predicate bbPred(BasicBlock post, BasicBlock pre) { post = pre.getASuccessor() }

Check warning

Code scanning / CodeQL

Missing QLDoc for parameter Warning

The QLDoc has no documentation for post, or pre, but the QLDoc mentions bbSucc
@aschackmull aschackmull force-pushed the java/basicblock branch 2 times, most recently from 5c50666 to 719bbe4 Compare May 19, 2025 07:37
Copy link
Contributor

@paldepind paldepind left a comment

Choose a reason for hiding this comment

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

Really awesome to get Java onto to the shared basic block library 😃

I've left a few minor comments and ideas.

/** Holds if this basic block post-dominates `node`. (This is reflexive.) */
predicate bbPostDominates(BasicBlock node) { bbPostDominates(this, node) }
/**
* A control-flow node that represents the start of a basic block.
Copy link
Contributor

Choose a reason for hiding this comment

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

This comment seems outdated as BasicBlock is no longer also a ControlFlowNode.

What about using the exact same QLDoc as for BasicBlock in the other languages (which we could modify if needed)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

---
category: deprecated
---
* Java now uses the shared `BasicBlock` library. This means that several member predicates now use the preferred names. The old predicates have been deprecated. The `BasicBlock` class itself no longer extends `ControlFlowNode` - the predicate `getFirstNode` can be used to fix any QL code that somehow relied on this.
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure if it's clear for end users what "the preferred names" refer to? Maybe mention that the naming of the member predicates are now aligned with other languages, which also gives it a positive spin.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed.

* ```
*/
predicate dominanceFrontier(BasicBlock x, BasicBlock w) {
x = w.getABBPredecessor() and not bbIDominates(x, w)
x = w.getAPredecessor() and not x.immediatelyDominates(w)
Copy link
Contributor

Choose a reason for hiding this comment

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

What about deprecating this in favor of inDominanceFrontier from the shared library?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think dominance frontier is used for anything else than SSA construction, and the shared SSA lib does its own calculation, so perhaps we should deprecate both. In any case, I think that's fine to postpone for now.


/** The immediate post-dominance relation on basic blocks. */
cached
predicate bbIPostDominates(BasicBlock dominator, BasicBlock node) =
deprecated predicate bbIPostDominates(BasicBlock dominator, BasicBlock node) =
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this have a DEPRECATED: Use ... doc like the other deprecated predicates?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Immediate post-dominance is not exposed in the shared lib - I'm not sure we've ever seen any use-cases for it, though, so adding it is probably of little value - hence why I simply opted to discretely deprecate this single public instance.

Comment on lines 249 to 251
* This is a necessary and sufficient condition for an edge to dominate anything,
* and in particular `dominatingEdge(bb1, bb2) and bb2.dominates(bb3)` means
* that the edge `(bb1, bb2)` dominates `bb3`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* This is a necessary and sufficient condition for an edge to dominate anything,
* and in particular `dominatingEdge(bb1, bb2) and bb2.dominates(bb3)` means
* that the edge `(bb1, bb2)` dominates `bb3`.
* This is a necessary and sufficient condition for an edge to dominate some
* node, and `dominatingEdge(bb1, bb2) and bb2.dominates(bb3)` implies that
* the edge `(bb1, bb2)` dominates `bb3`.

It might just be me, but I find "anything" here to be a bit unclear.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've adopted the s/anything/some node/, but I don't want to change the second sentence from "means" to "implies", as that weakens the statement - it really is the semantic meaning of the QL snippet that's being explained.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Or how about "something" instead? Or at the very least "some block"?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've gone with "some block" for now.

Copy link
Contributor

Choose a reason for hiding this comment

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

"Some block" is also great 👍

I don't really understand the "in particular" though. What follows doesn't seem like a special case of the preceding statement? "This" in the first part refers to dominatingEdge(bb1, bb2) and the second part talks about a situration where, in addition, bb2.dominates(bb3) holds as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right, I guess "in particular" ought to be "therefore". Does that sound better to you?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, I think "therefore" would be great :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

@@ -16,6 +16,6 @@ predicate dominanceCounterExample(ControlFlowNode entry, ControlFlowNode dom, Co

from Callable c, ControlFlowNode dom, ControlFlowNode node
where
(strictlyDominates(dom, node) or bbStrictlyDominates(dom, node)) and
strictlyDominates(dom, node) and
Copy link
Contributor

Choose a reason for hiding this comment

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

This is in a file that includes "wrong" in the name, so I'm guessing it doesn't matter, but it's not clear to me why the previous code had the two conjuncts.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Once upon a time dominance for individual cfg nodes was computed independently of basic blocks, which I believe is the historical reason for this double check. Now, when translating basic block dominance via getFirstNode, one implies the other trivially, so we can simplify the test.

*/
class BasicBlock extends BbImpl::BasicBlock {
/** Gets the immediately enclosing callable whose body contains this node. */
Callable getEnclosingCallable() { result = this.getScope() }
Copy link
Contributor

Choose a reason for hiding this comment

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

As discussed offline it might be nice to agree on a name for this predicate that every language can use. Right now Java's basic block will have both getScope and getEnclosingCallable that does the exact same thing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, but I think that's best left as a follow-up.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, absolutely :)

@aschackmull
Copy link
Contributor Author

@paldepind I've pushed review fixes now.

Copy link
Contributor

@paldepind paldepind left a comment

Choose a reason for hiding this comment

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

Thanks for addressing my nitpicks. Looks great to me 👍

@aschackmull aschackmull merged commit 00c7bc1 into github:main May 21, 2025
43 checks passed
@aschackmull aschackmull deleted the java/basicblock branch May 21, 2025 11:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy