mirror of
https://github.com/github/codeql.git
synced 2026-03-30 20:28:15 +02:00
Merge pull request #21412 from aschackmull/java/binary-assignment
Java: Make Assignment extend BinaryExpr.
This commit is contained in:
4
java/ql/lib/change-notes/2026-03-04-binary-assignment.md
Normal file
4
java/ql/lib/change-notes/2026-03-04-binary-assignment.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The class `Assignment` now extends `BinaryExpr`. Uses of `BinaryExpr` may in some cases need slight adjustment.
|
||||
@@ -815,6 +815,7 @@ when_branch_else(unique int id: @whenbranch ref);
|
||||
| @geexpr
|
||||
| @eqexpr
|
||||
| @neexpr
|
||||
| @assignment
|
||||
| @valueeqexpr
|
||||
| @valueneexpr;
|
||||
|
||||
|
||||
@@ -392,7 +392,7 @@ class ArrayInit extends Expr, @arrayinit {
|
||||
* element assignments since there the assignment destination is not directly
|
||||
* the array variable but instead an `ArrayAccess`.
|
||||
*/
|
||||
class Assignment extends Expr, @assignment {
|
||||
class Assignment extends BinaryExpr, @assignment {
|
||||
/** Gets the destination (left-hand side) of the assignment. */
|
||||
Expr getDest() { result.isNthChildOf(this, 0) }
|
||||
|
||||
@@ -417,6 +417,8 @@ class Assignment extends Expr, @assignment {
|
||||
* For example, `x = 23`.
|
||||
*/
|
||||
class AssignExpr extends Assignment, @assignexpr {
|
||||
override string getOp() { result = "=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssignExpr" }
|
||||
}
|
||||
|
||||
@@ -445,7 +447,7 @@ class AssignOp extends Assignment, @assignop {
|
||||
override Expr getSource() { result.getParent() = this }
|
||||
|
||||
/** Gets a string representation of the assignment operator of this compound assignment. */
|
||||
/*abstract*/ string getOp() { result = "??=" }
|
||||
/*abstract*/ override string getOp() { result = "??=" }
|
||||
|
||||
/** Gets a printable representation of this expression. */
|
||||
override string toString() { result = "..." + this.getOp() + "..." }
|
||||
@@ -739,155 +741,155 @@ class BinaryExpr extends Expr, @binaryexpr {
|
||||
}
|
||||
|
||||
/** Gets a printable representation of this expression. */
|
||||
override string toString() { result = "..." + this.getOp() + "..." }
|
||||
override string toString() { result = "... " + this.getOp() + " ..." }
|
||||
|
||||
/** Gets a string representation of the operator of this binary expression. */
|
||||
/*abstract*/ string getOp() { result = " ?? " }
|
||||
/*abstract*/ string getOp() { result = "??" }
|
||||
}
|
||||
|
||||
/** A binary expression using the `*` operator. */
|
||||
class MulExpr extends BinaryExpr, @mulexpr {
|
||||
override string getOp() { result = " * " }
|
||||
override string getOp() { result = "*" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "MulExpr" }
|
||||
}
|
||||
|
||||
/** A binary expression using the `/` operator. */
|
||||
class DivExpr extends BinaryExpr, @divexpr {
|
||||
override string getOp() { result = " / " }
|
||||
override string getOp() { result = "/" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "DivExpr" }
|
||||
}
|
||||
|
||||
/** A binary expression using the `%` operator. */
|
||||
class RemExpr extends BinaryExpr, @remexpr {
|
||||
override string getOp() { result = " % " }
|
||||
override string getOp() { result = "%" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "RemExpr" }
|
||||
}
|
||||
|
||||
/** A binary expression using the `+` operator. */
|
||||
class AddExpr extends BinaryExpr, @addexpr {
|
||||
override string getOp() { result = " + " }
|
||||
override string getOp() { result = "+" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AddExpr" }
|
||||
}
|
||||
|
||||
/** A binary expression using the `-` operator. */
|
||||
class SubExpr extends BinaryExpr, @subexpr {
|
||||
override string getOp() { result = " - " }
|
||||
override string getOp() { result = "-" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "SubExpr" }
|
||||
}
|
||||
|
||||
/** A binary expression using the `<<` operator. */
|
||||
class LeftShiftExpr extends BinaryExpr, @lshiftexpr {
|
||||
override string getOp() { result = " << " }
|
||||
override string getOp() { result = "<<" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LeftShiftExpr" }
|
||||
}
|
||||
|
||||
/** A binary expression using the `>>` operator. */
|
||||
class RightShiftExpr extends BinaryExpr, @rshiftexpr {
|
||||
override string getOp() { result = " >> " }
|
||||
override string getOp() { result = ">>" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "RightShiftExpr" }
|
||||
}
|
||||
|
||||
/** A binary expression using the `>>>` operator. */
|
||||
class UnsignedRightShiftExpr extends BinaryExpr, @urshiftexpr {
|
||||
override string getOp() { result = " >>> " }
|
||||
override string getOp() { result = ">>>" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "UnsignedRightShiftExpr" }
|
||||
}
|
||||
|
||||
/** A binary expression using the `&` operator. */
|
||||
class AndBitwiseExpr extends BinaryExpr, @andbitexpr {
|
||||
override string getOp() { result = " & " }
|
||||
override string getOp() { result = "&" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AndBitwiseExpr" }
|
||||
}
|
||||
|
||||
/** A binary expression using the `|` operator. */
|
||||
class OrBitwiseExpr extends BinaryExpr, @orbitexpr {
|
||||
override string getOp() { result = " | " }
|
||||
override string getOp() { result = "|" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "OrBitwiseExpr" }
|
||||
}
|
||||
|
||||
/** A binary expression using the `^` operator. */
|
||||
class XorBitwiseExpr extends BinaryExpr, @xorbitexpr {
|
||||
override string getOp() { result = " ^ " }
|
||||
override string getOp() { result = "^" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "XorBitwiseExpr" }
|
||||
}
|
||||
|
||||
/** A binary expression using the `&&` operator. */
|
||||
class AndLogicalExpr extends BinaryExpr, @andlogicalexpr {
|
||||
override string getOp() { result = " && " }
|
||||
override string getOp() { result = "&&" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AndLogicalExpr" }
|
||||
}
|
||||
|
||||
/** A binary expression using the `||` operator. */
|
||||
class OrLogicalExpr extends BinaryExpr, @orlogicalexpr {
|
||||
override string getOp() { result = " || " }
|
||||
override string getOp() { result = "||" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "OrLogicalExpr" }
|
||||
}
|
||||
|
||||
/** A binary expression using the `<` operator. */
|
||||
class LTExpr extends BinaryExpr, @ltexpr {
|
||||
override string getOp() { result = " < " }
|
||||
override string getOp() { result = "<" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LTExpr" }
|
||||
}
|
||||
|
||||
/** A binary expression using the `>` operator. */
|
||||
class GTExpr extends BinaryExpr, @gtexpr {
|
||||
override string getOp() { result = " > " }
|
||||
override string getOp() { result = ">" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "GTExpr" }
|
||||
}
|
||||
|
||||
/** A binary expression using the `<=` operator. */
|
||||
class LEExpr extends BinaryExpr, @leexpr {
|
||||
override string getOp() { result = " <= " }
|
||||
override string getOp() { result = "<=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LEExpr" }
|
||||
}
|
||||
|
||||
/** A binary expression using the `>=` operator. */
|
||||
class GEExpr extends BinaryExpr, @geexpr {
|
||||
override string getOp() { result = " >= " }
|
||||
override string getOp() { result = ">=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "GEExpr" }
|
||||
}
|
||||
|
||||
/** A binary expression using Java's `==` or Kotlin's `===` operator. */
|
||||
class EQExpr extends BinaryExpr, @eqexpr {
|
||||
override string getOp() { result = " == " }
|
||||
override string getOp() { result = "==" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "EQExpr" }
|
||||
}
|
||||
|
||||
/** A binary expression using the Kotlin `==` operator, semantically equivalent to `Objects.equals`. */
|
||||
class ValueEQExpr extends BinaryExpr, @valueeqexpr {
|
||||
override string getOp() { result = " (value equals) " }
|
||||
override string getOp() { result = "(value equals)" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ValueEQExpr" }
|
||||
}
|
||||
|
||||
/** A binary expression using Java's `!=` or Kotlin's `!==` operator. */
|
||||
class NEExpr extends BinaryExpr, @neexpr {
|
||||
override string getOp() { result = " != " }
|
||||
override string getOp() { result = "!=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "NEExpr" }
|
||||
}
|
||||
|
||||
/** A binary expression using the Kotlin `!=` operator, semantically equivalent to `Objects.equals`. */
|
||||
class ValueNEExpr extends BinaryExpr, @valueneexpr {
|
||||
override string getOp() { result = " (value not-equals) " }
|
||||
override string getOp() { result = "(value not-equals)" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ValueNEExpr" }
|
||||
}
|
||||
|
||||
@@ -207,29 +207,12 @@ private class PpArrayInit extends PpAst, ArrayInit {
|
||||
override PpAst getChild(int i) { exists(int j | result = this.getInit(j) and i = 1 + 2 * j) }
|
||||
}
|
||||
|
||||
private class PpAssignment extends PpAst, Assignment {
|
||||
override string getPart(int i) {
|
||||
i = 1 and
|
||||
this instanceof AssignExpr and
|
||||
result = " = "
|
||||
or
|
||||
i = 1 and
|
||||
result = " " + this.(AssignOp).getOp() + " "
|
||||
}
|
||||
|
||||
override PpAst getChild(int i) {
|
||||
i = 0 and result = this.getDest()
|
||||
or
|
||||
i = 2 and result = this.getRhs()
|
||||
}
|
||||
}
|
||||
|
||||
private class PpLiteral extends PpAst, Literal {
|
||||
override string getPart(int i) { i = 0 and result = this.getLiteral() }
|
||||
}
|
||||
|
||||
private class PpBinaryExpr extends PpAst, BinaryExpr {
|
||||
override string getPart(int i) { i = 1 and result = this.getOp() }
|
||||
override string getPart(int i) { i = 1 and result = " " + this.getOp() + " " }
|
||||
|
||||
override PpAst getChild(int i) {
|
||||
i = 0 and result = this.getLeftOperand()
|
||||
|
||||
@@ -93,8 +93,7 @@ class ArithExpr extends Expr {
|
||||
) and
|
||||
forall(Expr e |
|
||||
e = this.(BinaryExpr).getAnOperand() or
|
||||
e = this.(UnaryAssignExpr).getOperand() or
|
||||
e = this.(AssignOp).getSource()
|
||||
e = this.(UnaryAssignExpr).getOperand()
|
||||
|
|
||||
e.getType() instanceof NumType
|
||||
)
|
||||
@@ -114,21 +113,17 @@ class ArithExpr extends Expr {
|
||||
*/
|
||||
Expr getLeftOperand() {
|
||||
result = this.(BinaryExpr).getLeftOperand() or
|
||||
result = this.(UnaryAssignExpr).getOperand() or
|
||||
result = this.(AssignOp).getDest()
|
||||
result = this.(UnaryAssignExpr).getOperand()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the right-hand operand if this is a binary expression.
|
||||
*/
|
||||
Expr getRightOperand() {
|
||||
result = this.(BinaryExpr).getRightOperand() or result = this.(AssignOp).getRhs()
|
||||
}
|
||||
Expr getRightOperand() { result = this.(BinaryExpr).getRightOperand() }
|
||||
|
||||
/** Gets an operand of this arithmetic expression. */
|
||||
Expr getAnOperand() {
|
||||
result = this.(BinaryExpr).getAnOperand() or
|
||||
result = this.(UnaryAssignExpr).getOperand() or
|
||||
result = this.(AssignOp).getSource()
|
||||
result = this.(UnaryAssignExpr).getOperand()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,13 +179,7 @@ private module GuardsInput implements SharedGuards::InputSig<Location, ControlFl
|
||||
}
|
||||
}
|
||||
|
||||
abstract private class BinExpr extends Expr {
|
||||
Expr getAnOperand() {
|
||||
result = this.(BinaryExpr).getAnOperand() or result = this.(AssignOp).getSource()
|
||||
}
|
||||
}
|
||||
|
||||
class AndExpr extends BinExpr {
|
||||
class AndExpr extends BinaryExpr {
|
||||
AndExpr() {
|
||||
this instanceof AndBitwiseExpr or
|
||||
this instanceof AndLogicalExpr or
|
||||
@@ -193,7 +187,7 @@ private module GuardsInput implements SharedGuards::InputSig<Location, ControlFl
|
||||
}
|
||||
}
|
||||
|
||||
class OrExpr extends BinExpr {
|
||||
class OrExpr extends BinaryExpr {
|
||||
OrExpr() {
|
||||
this instanceof OrBitwiseExpr or
|
||||
this instanceof OrLogicalExpr or
|
||||
|
||||
@@ -53,8 +53,6 @@ private predicate unboxed(Expr e) {
|
||||
assign.getDest().getType() instanceof PrimitiveType and assign.getSource() = e
|
||||
)
|
||||
or
|
||||
exists(AssignOp assign | assign.getSource() = e and assign.getType() instanceof PrimitiveType)
|
||||
or
|
||||
exists(EqualityTest eq |
|
||||
eq.getAnOperand() = e and eq.getAnOperand().getType() instanceof PrimitiveType
|
||||
)
|
||||
@@ -62,6 +60,7 @@ private predicate unboxed(Expr e) {
|
||||
exists(BinaryExpr bin |
|
||||
bin.getAnOperand() = e and
|
||||
not bin instanceof EqualityTest and
|
||||
not bin instanceof AssignExpr and
|
||||
bin.getType() instanceof PrimitiveType
|
||||
)
|
||||
or
|
||||
|
||||
@@ -86,23 +86,7 @@ module Sem implements Semantic<Location> {
|
||||
|
||||
class ConstantIntegerExpr = RU::ConstantIntegerExpr;
|
||||
|
||||
abstract class BinaryExpr extends Expr {
|
||||
Expr getLeftOperand() {
|
||||
result = this.(J::BinaryExpr).getLeftOperand() or result = this.(J::AssignOp).getDest()
|
||||
}
|
||||
|
||||
Expr getRightOperand() {
|
||||
result = this.(J::BinaryExpr).getRightOperand() or result = this.(J::AssignOp).getRhs()
|
||||
}
|
||||
|
||||
final Expr getAnOperand() { result = this.getLeftOperand() or result = this.getRightOperand() }
|
||||
|
||||
final predicate hasOperands(Expr e1, Expr e2) {
|
||||
this.getLeftOperand() = e1 and this.getRightOperand() = e2
|
||||
or
|
||||
this.getLeftOperand() = e2 and this.getRightOperand() = e1
|
||||
}
|
||||
}
|
||||
class BinaryExpr = J::BinaryExpr;
|
||||
|
||||
class AddExpr extends BinaryExpr {
|
||||
AddExpr() { this instanceof J::AddExpr or this instanceof J::AssignAddExpr }
|
||||
|
||||
@@ -161,13 +161,9 @@ module Private {
|
||||
this instanceof J::AssignUnsignedRightShiftExpr and result = TUnsignedRightShiftOp()
|
||||
}
|
||||
|
||||
Expr getLeftOperand() {
|
||||
result = this.(J::BinaryExpr).getLeftOperand() or result = this.(J::AssignOp).getDest()
|
||||
}
|
||||
Expr getLeftOperand() { result = this.(J::BinaryExpr).getLeftOperand() }
|
||||
|
||||
Expr getRightOperand() {
|
||||
result = this.(J::BinaryExpr).getRightOperand() or result = this.(J::AssignOp).getRhs()
|
||||
}
|
||||
Expr getRightOperand() { result = this.(J::BinaryExpr).getRightOperand() }
|
||||
}
|
||||
|
||||
predicate ssaRead = RU::ssaRead/2;
|
||||
|
||||
@@ -73,7 +73,8 @@ module InsecureRandomnessConfig implements DataFlow::ConfigSig {
|
||||
predicate isBarrierOut(DataFlow::Node n) { isSink(n) }
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
n1.asExpr() = n2.asExpr().(BinaryExpr).getAnOperand()
|
||||
n1.asExpr() = n2.asExpr().(BinaryExpr).getAnOperand() and
|
||||
not n2.asExpr() instanceof AssignExpr
|
||||
or
|
||||
n1.asExpr() = n2.asExpr().(UnaryExpr).getOperand()
|
||||
or
|
||||
|
||||
@@ -31,10 +31,7 @@ class RightShiftOp extends Expr {
|
||||
this instanceof AssignUnsignedRightShiftExpr
|
||||
}
|
||||
|
||||
private Expr getLhs() {
|
||||
this.(BinaryExpr).getLeftOperand() = result or
|
||||
this.(Assignment).getDest() = result
|
||||
}
|
||||
private Expr getLhs() { this.(BinaryExpr).getLeftOperand() = result }
|
||||
|
||||
/**
|
||||
* Gets the variable that is shifted.
|
||||
|
||||
@@ -54,9 +54,8 @@ private module PredictableSeedFlowConfig implements DataFlow::ConfigSig {
|
||||
private module PredictableSeedFlow = DataFlow::Global<PredictableSeedFlowConfig>;
|
||||
|
||||
private predicate predictableCalcStep(Expr e1, Expr e2) {
|
||||
e2.(BinaryExpr).hasOperands(e1, any(PredictableSeedExpr p))
|
||||
or
|
||||
exists(AssignOp a | a = e2 | e1 = a.getDest() and a.getRhs() instanceof PredictableSeedExpr)
|
||||
e2.(BinaryExpr).hasOperands(e1, any(PredictableSeedExpr p)) and
|
||||
not e2 instanceof AssignExpr
|
||||
or
|
||||
exists(ConstructorCall cc, TypeNumber t | cc = e2 |
|
||||
cc.getArgument(0) = e1 and
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Expand @binaryexpr union to include @assignment
|
||||
compatibility: full
|
||||
Reference in New Issue
Block a user