From 6ffed8523cc7f2b401f6b14c8a050957cb93ddc2 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Wed, 11 Mar 2026 10:03:00 +0100 Subject: [PATCH] Cfg/Java: Move InstanceOfExpr CFG into shared lib. --- .../lib/semmle/code/java/ControlFlowGraph.qll | 42 ++++--------------- .../codeql/controlflow/ControlFlowGraph.qll | 39 +++++++++++++++++ 2 files changed, 47 insertions(+), 34 deletions(-) diff --git a/java/ql/lib/semmle/code/java/ControlFlowGraph.qll b/java/ql/lib/semmle/code/java/ControlFlowGraph.qll index 20d622e91c8..72353de39fc 100644 --- a/java/ql/lib/semmle/code/java/ControlFlowGraph.qll +++ b/java/ql/lib/semmle/code/java/ControlFlowGraph.qll @@ -208,6 +208,14 @@ private module Ast implements AstSig { class BooleanLiteral extends FinalBooleanLiteral { boolean getValue() { result = this.getBooleanValue() } } + + final private class FinalInstanceOfExpr = J::InstanceOfExpr; + + class PatternMatchExpr extends FinalInstanceOfExpr { + PatternMatchExpr() { this.isPattern() } + + AstNode getPattern() { result = super.getPattern() } + } } private module Exceptions { @@ -544,14 +552,8 @@ private module Input implements InputSig1, InputSig2 { private string assertThrowNodeTag() { result = "[assert-throw]" } - private string instanceofTrueNodeTag() { result = "[instanceof-true]" } - predicate additionalNode(Ast::AstNode n, string tag, NormalSuccessor t) { n instanceof AssertStmt and tag = assertThrowNodeTag() and t instanceof DirectSuccessor - or - n.(InstanceOfExpr).isPattern() and - tag = instanceofTrueNodeTag() and - t.(BooleanSuccessor).getValue() = true } /** @@ -593,34 +595,6 @@ private module Input implements InputSig1, InputSig2 { /** Holds if there is a local non-abrupt step from `n1` to `n2`. */ predicate step(PreControlFlowNode n1, PreControlFlowNode n2) { - exists(InstanceOfExpr ioe | - // common - n1.isBefore(ioe) and - n2.isBefore(ioe.getExpr()) - or - n1.isAfter(ioe.getExpr()) and - n2.isIn(ioe) - or - // std postorder: - not ioe.isPattern() and - n1.isIn(ioe) and - n2.isAfter(ioe) - or - // pattern case: - ioe.isPattern() and - n1.isIn(ioe) and - n2.isAfterValue(ioe, any(BooleanSuccessor s | s.getValue() = false)) - or - n1.isIn(ioe) and - n2.isAdditional(ioe, instanceofTrueNodeTag()) - or - n1.isAdditional(ioe, instanceofTrueNodeTag()) and - n2.isBefore(ioe.getPattern()) - or - n1.isAfter(ioe.getPattern()) and - n2.isAfterValue(ioe, any(BooleanSuccessor s | s.getValue() = true)) - ) - or exists(AssertStmt assertstmt | n1.isBefore(assertstmt) and n2.isBefore(assertstmt.getExpr()) diff --git a/shared/controlflow/codeql/controlflow/ControlFlowGraph.qll b/shared/controlflow/codeql/controlflow/ControlFlowGraph.qll index 8df466678cd..7cd169fa5f7 100644 --- a/shared/controlflow/codeql/controlflow/ControlFlowGraph.qll +++ b/shared/controlflow/codeql/controlflow/ControlFlowGraph.qll @@ -341,6 +341,19 @@ signature module AstSig { /** Gets the boolean value of this literal. */ boolean getValue(); } + + /** + * A pattern matching expression. + * + * In Java this is `x instanceof Pattern`, and in C# this is `x is Pattern`. + */ + class PatternMatchExpr extends Expr { + /** Gets the expression being matched. */ + Expr getExpr(); + + /** Gets the pattern being matched against. */ + AstNode getPattern(); + } } /** @@ -575,6 +588,8 @@ module Make0 Ast> { private string loopHeaderTag() { result = "[LoopHeader]" } + private string patternMatchTrueTag() { result = "[match-true]" } + /** * Holds if an additional node tagged with `tag` should be created for * `n`. Edges targeting such nodes are labeled with `t` and therefore `t` @@ -586,6 +601,10 @@ module Make0 Ast> { n instanceof LoopStmt and tag = loopHeaderTag() and t instanceof DirectSuccessor + or + n instanceof PatternMatchExpr and + tag = patternMatchTrueTag() and + t.(BooleanSuccessor).getValue() = true } /** @@ -1309,6 +1328,26 @@ module Make0 Ast> { n2.isAfterValue(boollit, any(BooleanSuccessor t | t.getValue() = boollit.getValue())) ) or + exists(PatternMatchExpr pme | + n1.isBefore(pme) and + n2.isBefore(pme.getExpr()) + or + n1.isAfter(pme.getExpr()) and + n2.isIn(pme) + or + n1.isIn(pme) and + n2.isAfterValue(pme, any(BooleanSuccessor s | s.getValue() = false)) + or + n1.isIn(pme) and + n2.isAdditional(pme, patternMatchTrueTag()) + or + n1.isAdditional(pme, patternMatchTrueTag()) and + n2.isBefore(pme.getPattern()) + or + n1.isAfter(pme.getPattern()) and + n2.isAfterValue(pme, any(BooleanSuccessor s | s.getValue() = true)) + ) + or exists(IfStmt ifstmt | n1.isBefore(ifstmt) and n2.isBefore(ifstmt.getCondition())