From 6042adebae6089df3a0d2f5b0f8599e6b485564b Mon Sep 17 00:00:00 2001 From: BazookaMusic Date: Wed, 27 May 2026 17:23:28 +0200 Subject: [PATCH 1/3] move identical java and cs bound.qll to shared library --- .../lib/semmle/code/java/dataflow/Bound.qll | 67 ++---------- .../internal/rangeanalysis/BoundSpecific.qll | 29 ++--- .../codeql/rangeanalysis/Bound.qll | 100 ++++++++++++++++++ 3 files changed, 125 insertions(+), 71 deletions(-) create mode 100644 shared/rangeanalysis/codeql/rangeanalysis/Bound.qll diff --git a/java/ql/lib/semmle/code/java/dataflow/Bound.qll b/java/ql/lib/semmle/code/java/dataflow/Bound.qll index 65af6fb13a81..a15880208387 100644 --- a/java/ql/lib/semmle/code/java/dataflow/Bound.qll +++ b/java/ql/lib/semmle/code/java/dataflow/Bound.qll @@ -4,67 +4,16 @@ overlay[local?] module; -private import internal.rangeanalysis.BoundSpecific +private import java as J +private import internal.rangeanalysis.BoundSpecific as BoundSpecific +private import codeql.rangeanalysis.Bound as SharedBound -private newtype TBound = - TBoundZero() or - TBoundSsa(SsaVariable v) { v.getSourceVariable().getType() instanceof IntegralType } or - TBoundExpr(Expr e) { - interestingExprBound(e) and - not exists(SsaVariable v | e = v.getAUse()) - } +module BoundInstantiation = SharedBound::Bound; -/** - * A bound that may be inferred for an expression plus/minus an integer delta. - */ -abstract class Bound extends TBound { - /** Gets a textual representation of this bound. */ - abstract string toString(); - - /** Gets an expression that equals this bound plus `delta`. */ - abstract Expr getExpr(int delta); - - /** Gets an expression that equals this bound. */ - Expr getExpr() { result = this.getExpr(0) } - - /** Gets the location of this bound. */ - abstract Location getLocation(); -} - -/** - * The bound that corresponds to the integer 0. This is used to represent all - * integer bounds as bounds are always accompanied by an added integer delta. - */ -class ZeroBound extends Bound, TBoundZero { - override string toString() { result = "0" } - - override Expr getExpr(int delta) { result.(ConstantIntegerExpr).getIntValue() = delta } +class Bound = BoundInstantiation::Bound; - override Location getLocation() { result.hasLocationInfo("", 0, 0, 0, 0) } -} - -/** - * A bound corresponding to the value of an SSA variable. - */ -class SsaBound extends Bound, TBoundSsa { - /** Gets the SSA variable that equals this bound. */ - SsaVariable getSsa() { this = TBoundSsa(result) } - - override string toString() { result = this.getSsa().toString() } - - override Expr getExpr(int delta) { result = this.getSsa().getAUse() and delta = 0 } - - override Location getLocation() { result = this.getSsa().getLocation() } -} - -/** - * A bound that corresponds to the value of a specific expression that might be - * interesting, but isn't otherwise represented by the value of an SSA variable. - */ -class ExprBound extends Bound, TBoundExpr { - override string toString() { result = this.getExpr().toString() } +class ZeroBound = BoundInstantiation::ZeroBound; - override Expr getExpr(int delta) { this = TBoundExpr(result) and delta = 0 } +class SsaBound = BoundInstantiation::SsaBound; - override Location getLocation() { result = this.getExpr().getLocation() } -} +class ExprBound = BoundInstantiation::ExprBound; \ No newline at end of file diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/BoundSpecific.qll b/java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/BoundSpecific.qll index cd85883f7bc4..ba2f8027b30f 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/BoundSpecific.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/BoundSpecific.qll @@ -7,21 +7,26 @@ module; private import java as J private import semmle.code.java.dataflow.SSA as Ssa private import semmle.code.java.dataflow.RangeUtils as RU +private import codeql.rangeanalysis.Bound as SharedBound -class SsaVariable extends Ssa::SsaDefinition { - /** Gets a use of this variable. */ - Expr getAUse() { result = super.getARead() } -} +module BoundDefs implements SharedBound::BoundDefinitions { + class SsaVariable extends Ssa::SsaDefinition { + /** Gets a use of this variable. */ + Expr getAUse() { result = super.getARead() } + } -class Expr = J::Expr; + class SsaSourceVariable = Ssa::SourceVariable; -class Location = J::Location; + class Type = J::Type; -class IntegralType = J::IntegralType; + class Expr = J::Expr; -class ConstantIntegerExpr = RU::ConstantIntegerExpr; + class IntegralType = J::IntegralType; -/** Holds if `e` is a bound expression and it is not an SSA variable read. */ -predicate interestingExprBound(Expr e) { - e.(J::FieldRead).getField() instanceof J::ArrayLengthField -} + class ConstantIntegerExpr = RU::ConstantIntegerExpr; + + /** Holds if `e` is a bound expression and it is not an SSA variable read. */ + predicate interestingExprBound(Expr e) { + e.(J::FieldRead).getField() instanceof J::ArrayLengthField + } +} \ No newline at end of file diff --git a/shared/rangeanalysis/codeql/rangeanalysis/Bound.qll b/shared/rangeanalysis/codeql/rangeanalysis/Bound.qll new file mode 100644 index 000000000000..10ef74d40010 --- /dev/null +++ b/shared/rangeanalysis/codeql/rangeanalysis/Bound.qll @@ -0,0 +1,100 @@ +/** + * Provides classes for representing abstract bounds for use in, for example, range analysis. + */ + +private import codeql.util.Location + +signature module BoundDefinitions { + class Type; + class IntegralType extends Type; + + class ConstantIntegerExpr extends Expr { + int getIntValue(); + } + + class SsaSourceVariable { + Type getType(); + } + + class SsaVariable { + SsaSourceVariable getSourceVariable(); + string toString(); + Location getLocation(); + Expr getAUse(); + } + + class Expr { + string toString(); + Location getLocation(); + } + + predicate interestingExprBound(Expr e); +} + +overlay[local?] +module Bound Defs> { + private import Defs + + private newtype TBound = + TBoundZero() or + TBoundSsa(SsaVariable v) { v.getSourceVariable().getType() instanceof IntegralType } or + TBoundExpr(Expr e) { + interestingExprBound(e) and + not exists(SsaVariable v | e = v.getAUse()) + } + + /** + * A bound that may be inferred for an expression plus/minus an integer delta. + */ + abstract class Bound extends TBound { + /** Gets a textual representation of this bound. */ + abstract string toString(); + + /** Gets an expression that equals this bound plus `delta`. */ + abstract Expr getExpr(int delta); + + /** Gets an expression that equals this bound. */ + Expr getExpr() { result = this.getExpr(0) } + + /** Gets the location of this bound. */ + abstract Location getLocation(); + } + + /** + * The bound that corresponds to the integer 0. This is used to represent all + * integer bounds as bounds are always accompanied by an added integer delta. + */ + class ZeroBound extends Bound, TBoundZero { + override string toString() { result = "0" } + + override Expr getExpr(int delta) { result.(ConstantIntegerExpr).getIntValue() = delta } + + override Location getLocation() { result.hasLocationInfo("", 0, 0, 0, 0) } + } + + /** + * A bound corresponding to the value of an SSA variable. + */ + class SsaBound extends Bound, TBoundSsa { + /** Gets the SSA variable that equals this bound. */ + SsaVariable getSsa() { this = TBoundSsa(result) } + + override string toString() { result = this.getSsa().toString() } + + override Expr getExpr(int delta) { result = this.getSsa().getAUse() and delta = 0 } + + override Location getLocation() { result = this.getSsa().getLocation() } + } + + /** + * A bound that corresponds to the value of a specific expression that might be + * interesting, but isn't otherwise represented by the value of an SSA variable. + */ + class ExprBound extends Bound, TBoundExpr { + override string toString() { result = this.getExpr().toString() } + + override Expr getExpr(int delta) { this = TBoundExpr(result) and delta = 0 } + + override Location getLocation() { result = this.getExpr().getLocation() } + } +} From acb5c0e70f56d981cec2f2e408b7a15247e4d818 Mon Sep 17 00:00:00 2001 From: BazookaMusic Date: Wed, 27 May 2026 17:23:45 +0200 Subject: [PATCH 2/3] missed changes --- csharp/ql/lib/qlpack.yml | 1 + .../lib/semmle/code/csharp/dataflow/Bound.qll | 52 +++---------------- .../internal/rangeanalysis/BoundSpecific.qll | 24 ++++++--- .../lib/semmle/code/java/dataflow/Bound.qll | 24 +++++++-- 4 files changed, 45 insertions(+), 56 deletions(-) diff --git a/csharp/ql/lib/qlpack.yml b/csharp/ql/lib/qlpack.yml index b3a0dab73036..8501130e2e7b 100644 --- a/csharp/ql/lib/qlpack.yml +++ b/csharp/ql/lib/qlpack.yml @@ -9,6 +9,7 @@ dependencies: codeql/controlflow: ${workspace} codeql/dataflow: ${workspace} codeql/mad: ${workspace} + codeql/rangeanalysis: ${workspace} codeql/ssa: ${workspace} codeql/threat-models: ${workspace} codeql/tutorial: ${workspace} diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/Bound.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/Bound.qll index 65af6fb13a81..b37222c1daa8 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/Bound.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/Bound.qll @@ -4,67 +4,31 @@ overlay[local?] module; +private import csharp as CS private import internal.rangeanalysis.BoundSpecific +private import internal.rangeanalysis.BoundSpecific as BoundSpecific +private import codeql.rangeanalysis.Bound as SharedBound -private newtype TBound = - TBoundZero() or - TBoundSsa(SsaVariable v) { v.getSourceVariable().getType() instanceof IntegralType } or - TBoundExpr(Expr e) { - interestingExprBound(e) and - not exists(SsaVariable v | e = v.getAUse()) - } +private module BoundImpl = SharedBound::Bound; /** * A bound that may be inferred for an expression plus/minus an integer delta. */ -abstract class Bound extends TBound { - /** Gets a textual representation of this bound. */ - abstract string toString(); - - /** Gets an expression that equals this bound plus `delta`. */ - abstract Expr getExpr(int delta); - - /** Gets an expression that equals this bound. */ - Expr getExpr() { result = this.getExpr(0) } - - /** Gets the location of this bound. */ - abstract Location getLocation(); -} +class Bound = BoundImpl::Bound; /** * The bound that corresponds to the integer 0. This is used to represent all * integer bounds as bounds are always accompanied by an added integer delta. */ -class ZeroBound extends Bound, TBoundZero { - override string toString() { result = "0" } - - override Expr getExpr(int delta) { result.(ConstantIntegerExpr).getIntValue() = delta } - - override Location getLocation() { result.hasLocationInfo("", 0, 0, 0, 0) } -} +class ZeroBound = BoundImpl::ZeroBound; /** * A bound corresponding to the value of an SSA variable. */ -class SsaBound extends Bound, TBoundSsa { - /** Gets the SSA variable that equals this bound. */ - SsaVariable getSsa() { this = TBoundSsa(result) } - - override string toString() { result = this.getSsa().toString() } - - override Expr getExpr(int delta) { result = this.getSsa().getAUse() and delta = 0 } - - override Location getLocation() { result = this.getSsa().getLocation() } -} +class SsaBound = BoundImpl::SsaBound; /** * A bound that corresponds to the value of a specific expression that might be * interesting, but isn't otherwise represented by the value of an SSA variable. */ -class ExprBound extends Bound, TBoundExpr { - override string toString() { result = this.getExpr().toString() } - - override Expr getExpr(int delta) { this = TBoundExpr(result) and delta = 0 } - - override Location getLocation() { result = this.getExpr().getLocation() } -} +class ExprBound = BoundImpl::ExprBound; \ No newline at end of file diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/BoundSpecific.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/BoundSpecific.qll index 037422684306..069f0034eed0 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/BoundSpecific.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/BoundSpecific.qll @@ -7,16 +7,26 @@ private import semmle.code.csharp.dataflow.SSA::Ssa as Ssa private import semmle.code.csharp.dataflow.internal.rangeanalysis.ConstantUtils as CU private import semmle.code.csharp.dataflow.internal.rangeanalysis.RangeUtils as RU private import semmle.code.csharp.dataflow.internal.rangeanalysis.SsaUtils as SU +private import codeql.rangeanalysis.Bound as SharedBound -class SsaVariable = SU::SsaVariable; +/** Holds if `e` is a bound expression and it is not an SSA variable read. */ -class Expr = CS::ControlFlowNodes::ExprNode; -class Location = CS::Location; +module BoundDefs implements SharedBound::BoundDefinitions { + class Type = CS::Type; -class IntegralType = CS::IntegralType; + class SsaVariable = SU::SsaVariable; + + class SsaSourceVariable = Ssa::SourceVariable; -class ConstantIntegerExpr = CU::ConstantIntegerExpr; + class Expr = CS::ControlFlowNodes::ExprNode; -/** Holds if `e` is a bound expression and it is not an SSA variable read. */ -predicate interestingExprBound(Expr e) { CU::systemArrayLengthAccess(e.getExpr()) } + class IntegralType = CS::IntegralType; + + class ConstantIntegerExpr = CU::ConstantIntegerExpr; + + /** Holds if `e` is a bound expression and it is not an SSA variable read. */ + predicate interestingExprBound(Expr e) { + CU::systemArrayLengthAccess(e.getExpr()) + } +} diff --git a/java/ql/lib/semmle/code/java/dataflow/Bound.qll b/java/ql/lib/semmle/code/java/dataflow/Bound.qll index a15880208387..0cfe3e9039d2 100644 --- a/java/ql/lib/semmle/code/java/dataflow/Bound.qll +++ b/java/ql/lib/semmle/code/java/dataflow/Bound.qll @@ -8,12 +8,26 @@ private import java as J private import internal.rangeanalysis.BoundSpecific as BoundSpecific private import codeql.rangeanalysis.Bound as SharedBound -module BoundInstantiation = SharedBound::Bound; +private module BoundImpl = SharedBound::Bound; -class Bound = BoundInstantiation::Bound; +/** + * A bound that may be inferred for an expression plus/minus an integer delta. + */ +class Bound = BoundImpl::Bound; -class ZeroBound = BoundInstantiation::ZeroBound; +/** + * The bound that corresponds to the integer 0. This is used to represent all + * integer bounds as bounds are always accompanied by an added integer delta. + */ +class ZeroBound = BoundImpl::ZeroBound; -class SsaBound = BoundInstantiation::SsaBound; +/** + * A bound corresponding to the value of an SSA variable. + */ +class SsaBound = BoundImpl::SsaBound; -class ExprBound = BoundInstantiation::ExprBound; \ No newline at end of file +/** + * A bound that corresponds to the value of a specific expression that might be + * interesting, but isn't otherwise represented by the value of an SSA variable. + */ +class ExprBound = BoundImpl::ExprBound; \ No newline at end of file From cc12740c0e55379ddfdb57be1f62f9322fa06927 Mon Sep 17 00:00:00 2001 From: BazookaMusic Date: Wed, 27 May 2026 17:41:44 +0200 Subject: [PATCH 3/3] remove check for files in sync --- config/identical-files.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/config/identical-files.json b/config/identical-files.json index 8a5c00a49f88..818f033e4db5 100644 --- a/config/identical-files.json +++ b/config/identical-files.json @@ -11,10 +11,6 @@ "java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll" ], - "Bound Java/C#": [ - "java/ql/lib/semmle/code/java/dataflow/Bound.qll", - "csharp/ql/lib/semmle/code/csharp/dataflow/Bound.qll" - ], "ModulusAnalysis Java/C#": [ "java/ql/lib/semmle/code/java/dataflow/ModulusAnalysis.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/ModulusAnalysis.qll"