Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
723a896
Cfg: Add ConditionKind and getDual to ConditionalSuccessor.
aschackmull Feb 5, 2026
2e98734
Java: Preparatory tweaks.
aschackmull Feb 6, 2026
4a97a44
Java: Replace ControlFlowNode.asCall with Call.getControlFlowNode.
aschackmull Feb 6, 2026
48d7d9c
Cfg: Add getEnclosingCallable to shared BasicBlock
aschackmull Feb 6, 2026
0c9931f
Java: Replace idominance tests.
aschackmull Feb 16, 2026
48e3724
Java/Cfg: Introduce new shared CFG library and replace the Java CFG.
aschackmull Jan 20, 2026
6fbdb2c
Java: Fix Cyclomatic complexity calculation.
aschackmull Feb 9, 2026
1e9dcea
Java: Fix RangeAnalysis/ModulusAnalysis.
aschackmull Feb 9, 2026
7871cd7
Java: Fix switchcase guards.
aschackmull Feb 9, 2026
12b9999
Java: Adjust BasicBlock-based qltests.
aschackmull Feb 10, 2026
fb2799b
Java: Adjust idominance tests.
aschackmull Feb 16, 2026
e0eb653
Java: Accept guards test changes for revised switch CFG.
aschackmull Feb 10, 2026
6ac8c4f
Java: Accept test changes due to pruned CFG, after-nodes, and reduced…
aschackmull Feb 10, 2026
a844d60
Java: Accept new CFG nodes.
aschackmull Feb 10, 2026
ccd28ff
Java: Fix instanceof-disjunction.
aschackmull Feb 11, 2026
fc8b7c0
Java: Exclude ExprStmt consistent with SwitchCase.getRuleExpression().
aschackmull Feb 11, 2026
581679d
Java: Fix reference to entry node.
aschackmull Feb 12, 2026
a6ee1df
Java: Remove test. Flexible constructors need AST-based tests, which …
aschackmull Feb 12, 2026
4d9c0e0
Java: Accept new locations for SSA definitions.
aschackmull Feb 12, 2026
a72cf56
Java: Accept dispatch precision improvement.
aschackmull Feb 12, 2026
b798bc2
Java: Fix enhancedForEarlyExit implementation.
aschackmull Feb 12, 2026
8b0dd7b
Java: Accept new TP in NullMaybe.
aschackmull Feb 12, 2026
d84e0e2
Java: Accept removal of spurious reason (the alert stays).
aschackmull Feb 12, 2026
106a9d4
Java: Accept reduced precision from no longer nesting completions in …
aschackmull Feb 12, 2026
eb37c41
Java: Accept revised CFG.
aschackmull Feb 13, 2026
352b371
Java: Remove obsolete tests - false successors are no longer special.
aschackmull Feb 16, 2026
f7317b6
Java: Enable Cfg consistency checks.
aschackmull Feb 16, 2026
d4873dd
Java: Adjust switch case guards test.
aschackmull Feb 16, 2026
0d0711f
Java: Add change note.
aschackmull Feb 18, 2026
bdbbd45
Java: Handle missing throws clauses.
aschackmull Feb 20, 2026
2b8e719
Java: Add nullness test covering known FP.
aschackmull Feb 23, 2026
94121f1
Guards: Improve join-order.
aschackmull Feb 23, 2026
ab94524
Cfg: Address review comments.
aschackmull Feb 27, 2026
627654c
Cfg: A few more review tweaks.
aschackmull Mar 2, 2026
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
6 changes: 0 additions & 6 deletions java/ql/lib/semmle/code/java/ControlFlowGraph.qll
Original file line number Diff line number Diff line change
Expand Up @@ -162,12 +162,6 @@ module ControlFlow {
/** Gets the expression this `Node` corresponds to, if any. */
Expr asExpr() { this = TExprNode(result) }

/** Gets the call this `Node` corresponds to, if any. */
Call asCall() {
result = this.asExpr() or
result = this.asStmt()
}

/** Gets a textual representation of this element. */
string toString() { none() }

Expand Down
9 changes: 9 additions & 0 deletions java/ql/lib/semmle/code/java/Expr.qll
Original file line number Diff line number Diff line change
Expand Up @@ -1245,6 +1245,9 @@ class ClassInstanceExpr extends Expr, ConstructorCall, @classinstancexpr {
/** Gets the immediately enclosing statement of this class instance creation expression. */
override Stmt getEnclosingStmt() { result = Expr.super.getEnclosingStmt() }

/** Gets the `ControlFlowNode` corresponding to this call. */
override ControlFlowNode getControlFlowNode() { result = Expr.super.getControlFlowNode() }

/** Gets a printable representation of this expression. */
override string toString() {
result = "new " + this.getConstructor().getName() + "(...)"
Expand Down Expand Up @@ -2113,6 +2116,9 @@ class MethodCall extends Expr, Call, @methodaccess {
/** Gets the immediately enclosing statement that contains this method access. */
override Stmt getEnclosingStmt() { result = Expr.super.getEnclosingStmt() }

/** Gets the `ControlFlowNode` corresponding to this call. */
override ControlFlowNode getControlFlowNode() { result = Expr.super.getControlFlowNode() }

/** Gets a printable representation of this expression. */
override string toString() {
if exists(this.getMethod())
Expand Down Expand Up @@ -2305,6 +2311,9 @@ class Call extends ExprParent, @caller {
/** Gets the enclosing statement of this call. */
/*abstract*/ Stmt getEnclosingStmt() { none() }

/** Gets the `ControlFlowNode` corresponding to this call. */
/*abstract*/ ControlFlowNode getControlFlowNode() { none() }

/** Gets the number of arguments provided in this call. */
int getNumArgument() { count(this.getAnArgument()) = result }

Expand Down
8 changes: 7 additions & 1 deletion java/ql/lib/semmle/code/java/Statement.qll
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class Stmt extends StmtParent, ExprParent, @stmt {
}

/** A statement parent is any element that can have a statement as its child. */
class StmtParent extends @stmtparent, Top { }
class StmtParent extends @stmtparent, ExprParent { }

/**
* An error statement.
Expand Down Expand Up @@ -960,6 +960,9 @@ class ThisConstructorInvocationStmt extends Stmt, ConstructorCall, @constructori
/** Gets the immediately enclosing statement of this constructor invocation. */
override Stmt getEnclosingStmt() { result = this }

/** Gets the `ControlFlowNode` corresponding to this call. */
override ControlFlowNode getControlFlowNode() { result = Stmt.super.getControlFlowNode() }

override string pp() { result = "this(...)" }

override string toString() { result = "this(...)" }
Expand Down Expand Up @@ -1001,6 +1004,9 @@ class SuperConstructorInvocationStmt extends Stmt, ConstructorCall, @superconstr
/** Gets the immediately enclosing statement of this constructor invocation. */
override Stmt getEnclosingStmt() { result = this }

/** Gets the `ControlFlowNode` corresponding to this call. */
override ControlFlowNode getControlFlowNode() { result = Stmt.super.getControlFlowNode() }

override string pp() { result = "super(...)" }

override string toString() { result = "super(...)" }
Expand Down
2 changes: 1 addition & 1 deletion java/ql/lib/semmle/code/java/controlflow/Paths.qll
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ abstract class ActionConfiguration extends string {
private BasicBlock actionBlock(ActionConfiguration conf) {
exists(ControlFlowNode node | result = node.getBasicBlock() |
conf.isAction(node) or
callAlwaysPerformsAction(node.asCall(), conf)
callAlwaysPerformsAction(any(Call call | call.getControlFlowNode() = node), conf)
)
}

Expand Down
2 changes: 1 addition & 1 deletion java/ql/lib/semmle/code/java/dataflow/InstanceAccess.qll
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ class InstanceAccessExt extends TInstanceAccessExt {
/** Gets the control flow node associated with this instance access. */
ControlFlowNode getCfgNode() {
exists(ExprParent e | e = this.getAssociatedExprOrStmt() |
result.asCall() = e
result = e.(Call).getControlFlowNode()
or
e.(InstanceAccess).getControlFlowNode() = result
or
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ private module BaseSsaImpl {
inner != outer and
inner.getDeclaringType() = innerclass and
result = parentDef(desugaredGetEnclosingType*(innerclass)) and
result.getEnclosingStmt().getEnclosingCallable() = outer and
result.getEnclosingCallable() = outer and
capturedvar = TLocalVar(outer, v) and
closurevar = TLocalVar(inner, v)
)
Expand Down
11 changes: 7 additions & 4 deletions java/ql/lib/semmle/code/java/dataflow/internal/SsaImpl.qll
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ private ControlFlowNode captureNode(TrackedVar capturedvar, TrackedVar closureva
inner != outer and
inner.getDeclaringType() = innerclass and
result = parentDef(desugaredGetEnclosingType*(innerclass)) and
result.getEnclosingStmt().getEnclosingCallable() = outer and
result.getEnclosingCallable() = outer and
capturedvar = TLocalVar(outer, v) and
closurevar = TLocalVar(inner, v)
)
Expand Down Expand Up @@ -153,7 +153,7 @@ private predicate hasEntryDef(TrackedVar v, BasicBlock b) {
overlay[global]
pragma[nomagic]
private predicate uncertainVariableUpdateImpl(TrackedVar v, ControlFlowNode n, BasicBlock b, int i) {
exists(Call c | c = n.asCall() | updatesNamedField(c, v, _)) and
exists(Call c | c.getControlFlowNode() = n | updatesNamedField(c, v, _)) and
b.getNode(i) = n and
hasDominanceInformation(b)
or
Expand Down Expand Up @@ -525,8 +525,11 @@ private module Cached {
overlay[global]
cached
predicate defUpdatesNamedField(SsaImplicitWrite calldef, TrackedField f, Callable setter) {
f = calldef.getSourceVariable() and
updatesNamedField0(calldef.getControlFlowNode().asCall(), f, setter)
exists(Call call |
f = calldef.getSourceVariable() and
call.getControlFlowNode() = calldef.getControlFlowNode() and
updatesNamedField0(call, f, setter)
)
}

/** Holds if `init` is a closure variable that captures the value of `capturedvar`. */
Expand Down
4 changes: 2 additions & 2 deletions java/ql/src/experimental/quantum/Examples/ArtifactReuse.qll
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ private DataFlow::Node getGeneratingWrapperSet(Crypto::NonceArtifactNode a) {
}

private predicate ancestorOfArtifact(
Crypto::ArtifactNode a, Callable enclosingCallable, ControlFlow::Node midOrTarget
Crypto::ArtifactNode a, Callable enclosingCallable, ControlFlowNode midOrTarget
) {
a.asElement().(Expr).getEnclosingCallable() = enclosingCallable and
(
Expand Down Expand Up @@ -87,7 +87,7 @@ predicate isArtifactReuse(Crypto::ArtifactNode a, Crypto::ArtifactNode b) {
ancestorOfArtifact(b, commonParent, _)
)
implies
exists(Callable commonParent, ControlFlow::Node aMid, ControlFlow::Node bMid |
exists(Callable commonParent, ControlFlowNode aMid, ControlFlowNode bMid |
ancestorOfArtifact(a, commonParent, aMid) and
ancestorOfArtifact(b, commonParent, bMid) and
a instanceof Crypto::NonceArtifactNode and
Expand Down
3 changes: 3 additions & 0 deletions shared/controlflow/codeql/controlflow/BasicBlock.qll
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,9 @@ module Make<LocationSig Location, InputSig<Location> Input> implements CfgSig<Lo
/** Gets the CFG scope of this basic block. */
CfgScope getScope() { result = nodeGetCfgScope(this.getFirstNode()) }

/** Gets the enclosing callable of this basic block. */
CfgScope getEnclosingCallable() { result = nodeGetCfgScope(this.getFirstNode()) }

/** Gets the location of this basic block. */
Location getLocation() { result = this.getFirstNode().getLocation() }

Expand Down
52 changes: 52 additions & 0 deletions shared/controlflow/codeql/controlflow/SuccessorType.qll
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,38 @@ module;

private import codeql.util.Boolean

private newtype TConditionKind =
TBooleanCondition() or
TNullnessCondition() or
TMatchingCondition() or
TEmptinessCondition()

/** A condition kind. This is used to classify different `ConditionalSuccessor`s. */
class ConditionKind extends TConditionKind {
/** Gets a textual representation of this condition kind. */
string toString() {
this instanceof TBooleanCondition and result = "Boolean"
or
this instanceof TNullnessCondition and result = "Nullness"
or
this instanceof TMatchingCondition and result = "Matching"
or
this instanceof TEmptinessCondition and result = "Emptiness"
}

/** Holds if this condition kind identifies `BooleanSuccessor`s. */
predicate isBoolean() { this instanceof TBooleanCondition }

/** Holds if this condition kind identifies `NullnessSuccessor`s. */
predicate isNullness() { this instanceof TNullnessCondition }

/** Holds if this condition kind identifies `MatchingSuccessor`s. */
predicate isMatching() { this instanceof TMatchingCondition }

/** Holds if this condition kind identifies `EmptinessSuccessor`s. */
predicate isEmptiness() { this instanceof TEmptinessCondition }
}

private newtype TSuccessorType =
TDirectSuccessor() or
TBooleanSuccessor(Boolean branch) or
Expand Down Expand Up @@ -83,6 +115,18 @@ private class TConditionalSuccessor =
abstract private class ConditionalSuccessorImpl extends NormalSuccessorImpl, TConditionalSuccessor {
/** Gets the Boolean value of this successor. */
abstract boolean getValue();

/** Gets the condition kind of this conditional successor. */
abstract ConditionKind getKind();

/**
* Gets the dual of this conditional successor. That is, the conditional
* successor of the same kind but with the opposite value.
*/
ConditionalSuccessor getDual() {
this.getValue().booleanNot() = result.getValue() and
this.getKind() = result.getKind()
}
}

final class ConditionalSuccessor = ConditionalSuccessorImpl;
Expand Down Expand Up @@ -116,6 +160,8 @@ final class ConditionalSuccessor = ConditionalSuccessorImpl;
class BooleanSuccessor extends ConditionalSuccessorImpl, TBooleanSuccessor {
override boolean getValue() { this = TBooleanSuccessor(result) }

override ConditionKind getKind() { result = TBooleanCondition() }

override string toString() { result = this.getValue().toString() }
}

Expand Down Expand Up @@ -151,6 +197,8 @@ class NullnessSuccessor extends ConditionalSuccessorImpl, TNullnessSuccessor {

override boolean getValue() { this = TNullnessSuccessor(result) }

override ConditionKind getKind() { result = TNullnessCondition() }

override string toString() { if this.isNull() then result = "null" else result = "non-null" }
}

Expand Down Expand Up @@ -192,6 +240,8 @@ class MatchingSuccessor extends ConditionalSuccessorImpl, TMatchingSuccessor {

override boolean getValue() { this = TMatchingSuccessor(result) }

override ConditionKind getKind() { result = TMatchingCondition() }

override string toString() { if this.isMatch() then result = "match" else result = "no-match" }
}

Expand Down Expand Up @@ -233,6 +283,8 @@ class EmptinessSuccessor extends ConditionalSuccessorImpl, TEmptinessSuccessor {

override boolean getValue() { this = TEmptinessSuccessor(result) }

override ConditionKind getKind() { result = TEmptinessCondition() }

override string toString() { if this.isEmpty() then result = "empty" else result = "non-empty" }
}

Expand Down